xref: /aosp_15_r20/external/libwebsockets/lib/roles/ws/ops-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 #define LWS_CPYAPP(ptr, str) { strcpy(ptr, str); ptr += strlen(str); }
28*1c60b9acSAndroid Build Coastguard Worker 
29*1c60b9acSAndroid Build Coastguard Worker /*
30*1c60b9acSAndroid Build Coastguard Worker  * client-parser.c: lws_ws_client_rx_sm() needs to be roughly kept in
31*1c60b9acSAndroid Build Coastguard Worker  *   sync with changes here, esp related to ext draining
32*1c60b9acSAndroid Build Coastguard Worker  */
33*1c60b9acSAndroid Build Coastguard Worker 
34*1c60b9acSAndroid Build Coastguard Worker int
lws_ws_rx_sm(struct lws * wsi,char already_processed,unsigned char c)35*1c60b9acSAndroid Build Coastguard Worker lws_ws_rx_sm(struct lws *wsi, char already_processed, unsigned char c)
36*1c60b9acSAndroid Build Coastguard Worker {
37*1c60b9acSAndroid Build Coastguard Worker 	int callback_action = LWS_CALLBACK_RECEIVE;
38*1c60b9acSAndroid Build Coastguard Worker 	struct lws_ext_pm_deflate_rx_ebufs pmdrx;
39*1c60b9acSAndroid Build Coastguard Worker 	unsigned short close_code;
40*1c60b9acSAndroid Build Coastguard Worker 	unsigned char *pp;
41*1c60b9acSAndroid Build Coastguard Worker 	int ret = 0;
42*1c60b9acSAndroid Build Coastguard Worker 	int n = 0;
43*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
44*1c60b9acSAndroid Build Coastguard Worker 	int rx_draining_ext = 0;
45*1c60b9acSAndroid Build Coastguard Worker 	int lin;
46*1c60b9acSAndroid Build Coastguard Worker #endif
47*1c60b9acSAndroid Build Coastguard Worker 
48*1c60b9acSAndroid Build Coastguard Worker 	pmdrx.eb_in.token = NULL;
49*1c60b9acSAndroid Build Coastguard Worker 	pmdrx.eb_in.len = 0;
50*1c60b9acSAndroid Build Coastguard Worker 	pmdrx.eb_out.token = NULL;
51*1c60b9acSAndroid Build Coastguard Worker 	pmdrx.eb_out.len = 0;
52*1c60b9acSAndroid Build Coastguard Worker 
53*1c60b9acSAndroid Build Coastguard Worker 	switch (wsi->lws_rx_parse_state) {
54*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_NEW:
55*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
56*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->ws->rx_draining_ext) {
57*1c60b9acSAndroid Build Coastguard Worker 			pmdrx.eb_in.token = NULL;
58*1c60b9acSAndroid Build Coastguard Worker 			pmdrx.eb_in.len = 0;
59*1c60b9acSAndroid Build Coastguard Worker 			pmdrx.eb_out.token = NULL;
60*1c60b9acSAndroid Build Coastguard Worker 			pmdrx.eb_out.len = 0;
61*1c60b9acSAndroid Build Coastguard Worker 			lws_remove_wsi_from_draining_ext_list(wsi);
62*1c60b9acSAndroid Build Coastguard Worker 			rx_draining_ext = 1;
63*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("%s: doing draining flow\n", __func__);
64*1c60b9acSAndroid Build Coastguard Worker 
65*1c60b9acSAndroid Build Coastguard Worker 			goto drain_extension;
66*1c60b9acSAndroid Build Coastguard Worker 		}
67*1c60b9acSAndroid Build Coastguard Worker #endif
68*1c60b9acSAndroid Build Coastguard Worker 		switch (wsi->ws->ietf_spec_revision) {
69*1c60b9acSAndroid Build Coastguard Worker 		case 13:
70*1c60b9acSAndroid Build Coastguard Worker 			/*
71*1c60b9acSAndroid Build Coastguard Worker 			 * no prepended frame key any more
72*1c60b9acSAndroid Build Coastguard Worker 			 */
73*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->all_zero_nonce = 1;
74*1c60b9acSAndroid Build Coastguard Worker 			goto handle_first;
75*1c60b9acSAndroid Build Coastguard Worker 
76*1c60b9acSAndroid Build Coastguard Worker 		default:
77*1c60b9acSAndroid Build Coastguard Worker 			lwsl_warn("lws_ws_rx_sm: unknown spec version %d\n",
78*1c60b9acSAndroid Build Coastguard Worker 				  wsi->ws->ietf_spec_revision);
79*1c60b9acSAndroid Build Coastguard Worker 			break;
80*1c60b9acSAndroid Build Coastguard Worker 		}
81*1c60b9acSAndroid Build Coastguard Worker 		break;
82*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_04_mask_1:
83*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->mask[1] = c;
84*1c60b9acSAndroid Build Coastguard Worker 		if (c)
85*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->all_zero_nonce = 0;
86*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_04_mask_2;
87*1c60b9acSAndroid Build Coastguard Worker 		break;
88*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_04_mask_2:
89*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->mask[2] = c;
90*1c60b9acSAndroid Build Coastguard Worker 		if (c)
91*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->all_zero_nonce = 0;
92*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_04_mask_3;
93*1c60b9acSAndroid Build Coastguard Worker 		break;
94*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_04_mask_3:
95*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->mask[3] = c;
96*1c60b9acSAndroid Build Coastguard Worker 		if (c)
97*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->all_zero_nonce = 0;
98*1c60b9acSAndroid Build Coastguard Worker 
99*1c60b9acSAndroid Build Coastguard Worker 		/*
100*1c60b9acSAndroid Build Coastguard Worker 		 * start from the zero'th byte in the XOR key buffer since
101*1c60b9acSAndroid Build Coastguard Worker 		 * this is the start of a frame with a new key
102*1c60b9acSAndroid Build Coastguard Worker 		 */
103*1c60b9acSAndroid Build Coastguard Worker 
104*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->mask_idx = 0;
105*1c60b9acSAndroid Build Coastguard Worker 
106*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_1;
107*1c60b9acSAndroid Build Coastguard Worker 		break;
108*1c60b9acSAndroid Build Coastguard Worker 
109*1c60b9acSAndroid Build Coastguard Worker 	/*
110*1c60b9acSAndroid Build Coastguard Worker 	 *  04 logical framing from the spec (all this is masked when incoming
111*1c60b9acSAndroid Build Coastguard Worker 	 *  and has to be unmasked)
112*1c60b9acSAndroid Build Coastguard Worker 	 *
113*1c60b9acSAndroid Build Coastguard Worker 	 * We ignore the possibility of extension data because we don't
114*1c60b9acSAndroid Build Coastguard Worker 	 * negotiate any extensions at the moment.
115*1c60b9acSAndroid Build Coastguard Worker 	 *
116*1c60b9acSAndroid Build Coastguard Worker 	 *    0                   1                   2                   3
117*1c60b9acSAndroid Build Coastguard Worker 	 *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
118*1c60b9acSAndroid Build Coastguard Worker 	 *   +-+-+-+-+-------+-+-------------+-------------------------------+
119*1c60b9acSAndroid Build Coastguard Worker 	 *   |F|R|R|R| opcode|R| Payload len |    Extended payload length    |
120*1c60b9acSAndroid Build Coastguard Worker 	 *   |I|S|S|S|  (4)  |S|     (7)     |             (16/63)           |
121*1c60b9acSAndroid Build Coastguard Worker 	 *   |N|V|V|V|       |V|             |   (if payload len==126/127)   |
122*1c60b9acSAndroid Build Coastguard Worker 	 *   | |1|2|3|       |4|             |                               |
123*1c60b9acSAndroid Build Coastguard Worker 	 *   +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
124*1c60b9acSAndroid Build Coastguard Worker 	 *   |     Extended payload length continued, if payload len == 127  |
125*1c60b9acSAndroid Build Coastguard Worker 	 *   + - - - - - - - - - - - - - - - +-------------------------------+
126*1c60b9acSAndroid Build Coastguard Worker 	 *   |                               |         Extension data        |
127*1c60b9acSAndroid Build Coastguard Worker 	 *   +-------------------------------+ - - - - - - - - - - - - - - - +
128*1c60b9acSAndroid Build Coastguard Worker 	 *   :                                                               :
129*1c60b9acSAndroid Build Coastguard Worker 	 *   +---------------------------------------------------------------+
130*1c60b9acSAndroid Build Coastguard Worker 	 *   :                       Application data                        :
131*1c60b9acSAndroid Build Coastguard Worker 	 *   +---------------------------------------------------------------+
132*1c60b9acSAndroid Build Coastguard Worker 	 *
133*1c60b9acSAndroid Build Coastguard Worker 	 *  We pass payload through to userland as soon as we get it, ignoring
134*1c60b9acSAndroid Build Coastguard Worker 	 *  FIN.  It's up to userland to buffer it up if it wants to see a
135*1c60b9acSAndroid Build Coastguard Worker 	 *  whole unfragmented block of the original size (which may be up to
136*1c60b9acSAndroid Build Coastguard Worker 	 *  2^63 long!)
137*1c60b9acSAndroid Build Coastguard Worker 	 */
138*1c60b9acSAndroid Build Coastguard Worker 
139*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_04_FRAME_HDR_1:
140*1c60b9acSAndroid Build Coastguard Worker handle_first:
141*1c60b9acSAndroid Build Coastguard Worker 
142*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->opcode = c & 0xf;
143*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->rsv = c & 0x70;
144*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->final = !!((c >> 7) & 1);
145*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->defeat_check_utf8 = 0;
146*1c60b9acSAndroid Build Coastguard Worker 
147*1c60b9acSAndroid Build Coastguard Worker 		if (((wsi->ws->opcode) & 8) && !wsi->ws->final) {
148*1c60b9acSAndroid Build Coastguard Worker 			lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR,
149*1c60b9acSAndroid Build Coastguard Worker 					(uint8_t *)"frag ctl", 8);
150*1c60b9acSAndroid Build Coastguard Worker 			return -1;
151*1c60b9acSAndroid Build Coastguard Worker 		}
152*1c60b9acSAndroid Build Coastguard Worker 
153*1c60b9acSAndroid Build Coastguard Worker 		switch (wsi->ws->opcode) {
154*1c60b9acSAndroid Build Coastguard Worker 		case LWSWSOPC_TEXT_FRAME:
155*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->check_utf8 = lws_check_opt(
156*1c60b9acSAndroid Build Coastguard Worker 				wsi->a.context->options,
157*1c60b9acSAndroid Build Coastguard Worker 				LWS_SERVER_OPTION_VALIDATE_UTF8);
158*1c60b9acSAndroid Build Coastguard Worker 			/* fallthru */
159*1c60b9acSAndroid Build Coastguard Worker 		case LWSWSOPC_BINARY_FRAME:
160*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->ws->opcode == LWSWSOPC_BINARY_FRAME)
161*1c60b9acSAndroid Build Coastguard Worker 				wsi->ws->check_utf8 = 0;
162*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->ws->continuation_possible) {
163*1c60b9acSAndroid Build Coastguard Worker 				lws_close_reason(wsi,
164*1c60b9acSAndroid Build Coastguard Worker 					LWS_CLOSE_STATUS_PROTOCOL_ERR,
165*1c60b9acSAndroid Build Coastguard Worker 					(uint8_t *)"bad cont", 8);
166*1c60b9acSAndroid Build Coastguard Worker 				return -1;
167*1c60b9acSAndroid Build Coastguard Worker 			}
168*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->rsv_first_msg = (c & 0x70);
169*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
170*1c60b9acSAndroid Build Coastguard Worker 			/*
171*1c60b9acSAndroid Build Coastguard Worker 			 *  set the expectation that we will have to
172*1c60b9acSAndroid Build Coastguard Worker 			 * fake up the zlib trailer to the inflator for this
173*1c60b9acSAndroid Build Coastguard Worker 			 * frame
174*1c60b9acSAndroid Build Coastguard Worker 			 */
175*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->pmd_trailer_application = !!(c & 0x40);
176*1c60b9acSAndroid Build Coastguard Worker #endif
177*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->frame_is_binary =
178*1c60b9acSAndroid Build Coastguard Worker 			     wsi->ws->opcode == LWSWSOPC_BINARY_FRAME;
179*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->first_fragment = 1;
180*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->continuation_possible = !wsi->ws->final;
181*1c60b9acSAndroid Build Coastguard Worker 			break;
182*1c60b9acSAndroid Build Coastguard Worker 		case LWSWSOPC_CONTINUATION:
183*1c60b9acSAndroid Build Coastguard Worker 			if (!wsi->ws->continuation_possible) {
184*1c60b9acSAndroid Build Coastguard Worker 				lws_close_reason(wsi,
185*1c60b9acSAndroid Build Coastguard Worker 					LWS_CLOSE_STATUS_PROTOCOL_ERR,
186*1c60b9acSAndroid Build Coastguard Worker 					(uint8_t *)"bad cont", 8);
187*1c60b9acSAndroid Build Coastguard Worker 				return -1;
188*1c60b9acSAndroid Build Coastguard Worker 			}
189*1c60b9acSAndroid Build Coastguard Worker 			break;
190*1c60b9acSAndroid Build Coastguard Worker 		case LWSWSOPC_CLOSE:
191*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->check_utf8 = 0;
192*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->utf8 = 0;
193*1c60b9acSAndroid Build Coastguard Worker 			break;
194*1c60b9acSAndroid Build Coastguard Worker 		case 3:
195*1c60b9acSAndroid Build Coastguard Worker 		case 4:
196*1c60b9acSAndroid Build Coastguard Worker 		case 5:
197*1c60b9acSAndroid Build Coastguard Worker 		case 6:
198*1c60b9acSAndroid Build Coastguard Worker 		case 7:
199*1c60b9acSAndroid Build Coastguard Worker 		case 0xb:
200*1c60b9acSAndroid Build Coastguard Worker 		case 0xc:
201*1c60b9acSAndroid Build Coastguard Worker 		case 0xd:
202*1c60b9acSAndroid Build Coastguard Worker 		case 0xe:
203*1c60b9acSAndroid Build Coastguard Worker 		case 0xf:
204*1c60b9acSAndroid Build Coastguard Worker 			lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR,
205*1c60b9acSAndroid Build Coastguard Worker 					(uint8_t *)"bad opc", 7);
206*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("illegal opcode\n");
207*1c60b9acSAndroid Build Coastguard Worker 			return -1;
208*1c60b9acSAndroid Build Coastguard Worker 		}
209*1c60b9acSAndroid Build Coastguard Worker 
210*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->ws->owed_a_fin &&
211*1c60b9acSAndroid Build Coastguard Worker 		    (wsi->ws->opcode == LWSWSOPC_TEXT_FRAME ||
212*1c60b9acSAndroid Build Coastguard Worker 		     wsi->ws->opcode == LWSWSOPC_BINARY_FRAME)) {
213*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("hey you owed us a FIN\n");
214*1c60b9acSAndroid Build Coastguard Worker 			lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR,
215*1c60b9acSAndroid Build Coastguard Worker 					(uint8_t *)"bad fin", 7);
216*1c60b9acSAndroid Build Coastguard Worker 			return -1;
217*1c60b9acSAndroid Build Coastguard Worker 		}
218*1c60b9acSAndroid Build Coastguard Worker 		if ((!(wsi->ws->opcode & 8)) && wsi->ws->final) {
219*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->continuation_possible = 0;
220*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->owed_a_fin = 0;
221*1c60b9acSAndroid Build Coastguard Worker 		}
222*1c60b9acSAndroid Build Coastguard Worker 
223*1c60b9acSAndroid Build Coastguard Worker 		if (!wsi->ws->final)
224*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->owed_a_fin = 1;
225*1c60b9acSAndroid Build Coastguard Worker 
226*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
227*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->ws->rsv &&
228*1c60b9acSAndroid Build Coastguard Worker 		    (
229*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
230*1c60b9acSAndroid Build Coastguard Worker 				    !wsi->ws->count_act_ext ||
231*1c60b9acSAndroid Build Coastguard Worker #endif
232*1c60b9acSAndroid Build Coastguard Worker 				    (wsi->ws->rsv & ~0x40))) {
233*1c60b9acSAndroid Build Coastguard Worker 			lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR,
234*1c60b9acSAndroid Build Coastguard Worker 					 (uint8_t *)"rsv bits", 8);
235*1c60b9acSAndroid Build Coastguard Worker 			return -1;
236*1c60b9acSAndroid Build Coastguard Worker 		}
237*1c60b9acSAndroid Build Coastguard Worker 		break;
238*1c60b9acSAndroid Build Coastguard Worker 
239*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_04_FRAME_HDR_LEN:
240*1c60b9acSAndroid Build Coastguard Worker 
241*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->this_frame_masked = !!(c & 0x80);
242*1c60b9acSAndroid Build Coastguard Worker 
243*1c60b9acSAndroid Build Coastguard Worker 		switch (c & 0x7f) {
244*1c60b9acSAndroid Build Coastguard Worker 		case 126:
245*1c60b9acSAndroid Build Coastguard Worker 			/* control frames are not allowed to have big lengths */
246*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->ws->opcode & 8)
247*1c60b9acSAndroid Build Coastguard Worker 				goto illegal_ctl_length;
248*1c60b9acSAndroid Build Coastguard Worker 
249*1c60b9acSAndroid Build Coastguard Worker 			wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
250*1c60b9acSAndroid Build Coastguard Worker 			break;
251*1c60b9acSAndroid Build Coastguard Worker 		case 127:
252*1c60b9acSAndroid Build Coastguard Worker 			/* control frames are not allowed to have big lengths */
253*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->ws->opcode & 8)
254*1c60b9acSAndroid Build Coastguard Worker 				goto illegal_ctl_length;
255*1c60b9acSAndroid Build Coastguard Worker 
256*1c60b9acSAndroid Build Coastguard Worker 			wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
257*1c60b9acSAndroid Build Coastguard Worker 			break;
258*1c60b9acSAndroid Build Coastguard Worker 		default:
259*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->rx_packet_length = c & 0x7f;
260*1c60b9acSAndroid Build Coastguard Worker 
261*1c60b9acSAndroid Build Coastguard Worker 
262*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->ws->this_frame_masked)
263*1c60b9acSAndroid Build Coastguard Worker 				wsi->lws_rx_parse_state =
264*1c60b9acSAndroid Build Coastguard Worker 						LWS_RXPS_07_COLLECT_FRAME_KEY_1;
265*1c60b9acSAndroid Build Coastguard Worker 			else
266*1c60b9acSAndroid Build Coastguard Worker 				if (wsi->ws->rx_packet_length) {
267*1c60b9acSAndroid Build Coastguard Worker 					wsi->lws_rx_parse_state =
268*1c60b9acSAndroid Build Coastguard Worker 					LWS_RXPS_WS_FRAME_PAYLOAD;
269*1c60b9acSAndroid Build Coastguard Worker 				} else {
270*1c60b9acSAndroid Build Coastguard Worker 					wsi->lws_rx_parse_state = LWS_RXPS_NEW;
271*1c60b9acSAndroid Build Coastguard Worker 					goto spill;
272*1c60b9acSAndroid Build Coastguard Worker 				}
273*1c60b9acSAndroid Build Coastguard Worker 			break;
274*1c60b9acSAndroid Build Coastguard Worker 		}
275*1c60b9acSAndroid Build Coastguard Worker 		break;
276*1c60b9acSAndroid Build Coastguard Worker 
277*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_04_FRAME_HDR_LEN16_2:
278*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->rx_packet_length = (size_t)(c << 8);
279*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
280*1c60b9acSAndroid Build Coastguard Worker 		break;
281*1c60b9acSAndroid Build Coastguard Worker 
282*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_04_FRAME_HDR_LEN16_1:
283*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->rx_packet_length |= c;
284*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->ws->this_frame_masked)
285*1c60b9acSAndroid Build Coastguard Worker 			wsi->lws_rx_parse_state =
286*1c60b9acSAndroid Build Coastguard Worker 					LWS_RXPS_07_COLLECT_FRAME_KEY_1;
287*1c60b9acSAndroid Build Coastguard Worker 		else {
288*1c60b9acSAndroid Build Coastguard Worker 			wsi->lws_rx_parse_state =
289*1c60b9acSAndroid Build Coastguard Worker 				LWS_RXPS_WS_FRAME_PAYLOAD;
290*1c60b9acSAndroid Build Coastguard Worker 		}
291*1c60b9acSAndroid Build Coastguard Worker 		break;
292*1c60b9acSAndroid Build Coastguard Worker 
293*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_04_FRAME_HDR_LEN64_8:
294*1c60b9acSAndroid Build Coastguard Worker 		if (c & 0x80) {
295*1c60b9acSAndroid Build Coastguard Worker 			lwsl_warn("b63 of length must be zero\n");
296*1c60b9acSAndroid Build Coastguard Worker 			/* kill the connection */
297*1c60b9acSAndroid Build Coastguard Worker 			return -1;
298*1c60b9acSAndroid Build Coastguard Worker 		}
299*1c60b9acSAndroid Build Coastguard Worker #if defined __LP64__
300*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->rx_packet_length = ((size_t)c) << 56;
301*1c60b9acSAndroid Build Coastguard Worker #else
302*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->rx_packet_length = 0;
303*1c60b9acSAndroid Build Coastguard Worker #endif
304*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
305*1c60b9acSAndroid Build Coastguard Worker 		break;
306*1c60b9acSAndroid Build Coastguard Worker 
307*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_04_FRAME_HDR_LEN64_7:
308*1c60b9acSAndroid Build Coastguard Worker #if defined __LP64__
309*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->rx_packet_length |= ((size_t)c) << 48;
310*1c60b9acSAndroid Build Coastguard Worker #endif
311*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
312*1c60b9acSAndroid Build Coastguard Worker 		break;
313*1c60b9acSAndroid Build Coastguard Worker 
314*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_04_FRAME_HDR_LEN64_6:
315*1c60b9acSAndroid Build Coastguard Worker #if defined __LP64__
316*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->rx_packet_length |= ((size_t)c) << 40;
317*1c60b9acSAndroid Build Coastguard Worker #endif
318*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
319*1c60b9acSAndroid Build Coastguard Worker 		break;
320*1c60b9acSAndroid Build Coastguard Worker 
321*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_04_FRAME_HDR_LEN64_5:
322*1c60b9acSAndroid Build Coastguard Worker #if defined __LP64__
323*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->rx_packet_length |= ((size_t)c) << 32;
324*1c60b9acSAndroid Build Coastguard Worker #endif
325*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
326*1c60b9acSAndroid Build Coastguard Worker 		break;
327*1c60b9acSAndroid Build Coastguard Worker 
328*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_04_FRAME_HDR_LEN64_4:
329*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->rx_packet_length |= ((size_t)c) << 24;
330*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
331*1c60b9acSAndroid Build Coastguard Worker 		break;
332*1c60b9acSAndroid Build Coastguard Worker 
333*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_04_FRAME_HDR_LEN64_3:
334*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->rx_packet_length |= ((size_t)c) << 16;
335*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
336*1c60b9acSAndroid Build Coastguard Worker 		break;
337*1c60b9acSAndroid Build Coastguard Worker 
338*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_04_FRAME_HDR_LEN64_2:
339*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->rx_packet_length |= ((size_t)c) << 8;
340*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
341*1c60b9acSAndroid Build Coastguard Worker 		break;
342*1c60b9acSAndroid Build Coastguard Worker 
343*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_04_FRAME_HDR_LEN64_1:
344*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->rx_packet_length |= ((size_t)c);
345*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->ws->this_frame_masked)
346*1c60b9acSAndroid Build Coastguard Worker 			wsi->lws_rx_parse_state =
347*1c60b9acSAndroid Build Coastguard Worker 					LWS_RXPS_07_COLLECT_FRAME_KEY_1;
348*1c60b9acSAndroid Build Coastguard Worker 		else
349*1c60b9acSAndroid Build Coastguard Worker 			wsi->lws_rx_parse_state = LWS_RXPS_WS_FRAME_PAYLOAD;
350*1c60b9acSAndroid Build Coastguard Worker 		break;
351*1c60b9acSAndroid Build Coastguard Worker 
352*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
353*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->mask[0] = c;
354*1c60b9acSAndroid Build Coastguard Worker 		if (c)
355*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->all_zero_nonce = 0;
356*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
357*1c60b9acSAndroid Build Coastguard Worker 		break;
358*1c60b9acSAndroid Build Coastguard Worker 
359*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
360*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->mask[1] = c;
361*1c60b9acSAndroid Build Coastguard Worker 		if (c)
362*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->all_zero_nonce = 0;
363*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
364*1c60b9acSAndroid Build Coastguard Worker 		break;
365*1c60b9acSAndroid Build Coastguard Worker 
366*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
367*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->mask[2] = c;
368*1c60b9acSAndroid Build Coastguard Worker 		if (c)
369*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->all_zero_nonce = 0;
370*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
371*1c60b9acSAndroid Build Coastguard Worker 		break;
372*1c60b9acSAndroid Build Coastguard Worker 
373*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
374*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->mask[3] = c;
375*1c60b9acSAndroid Build Coastguard Worker 		if (c)
376*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->all_zero_nonce = 0;
377*1c60b9acSAndroid Build Coastguard Worker 		wsi->lws_rx_parse_state = LWS_RXPS_WS_FRAME_PAYLOAD;
378*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->mask_idx = 0;
379*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->ws->rx_packet_length == 0) {
380*1c60b9acSAndroid Build Coastguard Worker 			wsi->lws_rx_parse_state = LWS_RXPS_NEW;
381*1c60b9acSAndroid Build Coastguard Worker 			goto spill;
382*1c60b9acSAndroid Build Coastguard Worker 		}
383*1c60b9acSAndroid Build Coastguard Worker 		break;
384*1c60b9acSAndroid Build Coastguard Worker 
385*1c60b9acSAndroid Build Coastguard Worker 
386*1c60b9acSAndroid Build Coastguard Worker 	case LWS_RXPS_WS_FRAME_PAYLOAD:
387*1c60b9acSAndroid Build Coastguard Worker 		assert(wsi->ws->rx_ubuf);
388*1c60b9acSAndroid Build Coastguard Worker 
389*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->ws->rx_ubuf_head + LWS_PRE >= wsi->ws->rx_ubuf_alloc) {
390*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("Attempted overflow \n");
391*1c60b9acSAndroid Build Coastguard Worker 			return -1;
392*1c60b9acSAndroid Build Coastguard Worker 		}
393*1c60b9acSAndroid Build Coastguard Worker 		if (!(already_processed & ALREADY_PROCESSED_IGNORE_CHAR)) {
394*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->ws->all_zero_nonce)
395*1c60b9acSAndroid Build Coastguard Worker 				wsi->ws->rx_ubuf[LWS_PRE +
396*1c60b9acSAndroid Build Coastguard Worker 				                 (wsi->ws->rx_ubuf_head++)] = c;
397*1c60b9acSAndroid Build Coastguard Worker 			else
398*1c60b9acSAndroid Build Coastguard Worker 				wsi->ws->rx_ubuf[LWS_PRE +
399*1c60b9acSAndroid Build Coastguard Worker 				                 (wsi->ws->rx_ubuf_head++)] =
400*1c60b9acSAndroid Build Coastguard Worker 				   c ^ wsi->ws->mask[(wsi->ws->mask_idx++) & 3];
401*1c60b9acSAndroid Build Coastguard Worker 
402*1c60b9acSAndroid Build Coastguard Worker 			--wsi->ws->rx_packet_length;
403*1c60b9acSAndroid Build Coastguard Worker 		}
404*1c60b9acSAndroid Build Coastguard Worker 
405*1c60b9acSAndroid Build Coastguard Worker 		if (!wsi->ws->rx_packet_length) {
406*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("%s: ws fragment length exhausted\n",
407*1c60b9acSAndroid Build Coastguard Worker 				   __func__);
408*1c60b9acSAndroid Build Coastguard Worker 			/* spill because we have the whole frame */
409*1c60b9acSAndroid Build Coastguard Worker 			wsi->lws_rx_parse_state = LWS_RXPS_NEW;
410*1c60b9acSAndroid Build Coastguard Worker 			goto spill;
411*1c60b9acSAndroid Build Coastguard Worker 		}
412*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
413*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->ws->rx_draining_ext) {
414*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("%s: UNTIL_EXHAUSTED draining\n", __func__);
415*1c60b9acSAndroid Build Coastguard Worker 			goto drain_extension;
416*1c60b9acSAndroid Build Coastguard Worker 		}
417*1c60b9acSAndroid Build Coastguard Worker #endif
418*1c60b9acSAndroid Build Coastguard Worker 		/*
419*1c60b9acSAndroid Build Coastguard Worker 		 * if there's no protocol max frame size given, we are
420*1c60b9acSAndroid Build Coastguard Worker 		 * supposed to default to context->pt_serv_buf_size
421*1c60b9acSAndroid Build Coastguard Worker 		 */
422*1c60b9acSAndroid Build Coastguard Worker 		if (!wsi->a.protocol->rx_buffer_size &&
423*1c60b9acSAndroid Build Coastguard Worker 		    wsi->ws->rx_ubuf_head != wsi->a.context->pt_serv_buf_size)
424*1c60b9acSAndroid Build Coastguard Worker 			break;
425*1c60b9acSAndroid Build Coastguard Worker 
426*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->a.protocol->rx_buffer_size &&
427*1c60b9acSAndroid Build Coastguard Worker 		    wsi->ws->rx_ubuf_head != wsi->a.protocol->rx_buffer_size)
428*1c60b9acSAndroid Build Coastguard Worker 			break;
429*1c60b9acSAndroid Build Coastguard Worker 
430*1c60b9acSAndroid Build Coastguard Worker 		/* spill because we filled our rx buffer */
431*1c60b9acSAndroid Build Coastguard Worker spill:
432*1c60b9acSAndroid Build Coastguard Worker 		/*
433*1c60b9acSAndroid Build Coastguard Worker 		 * is this frame a control packet we should take care of at this
434*1c60b9acSAndroid Build Coastguard Worker 		 * layer?  If so service it and hide it from the user callback
435*1c60b9acSAndroid Build Coastguard Worker 		 */
436*1c60b9acSAndroid Build Coastguard Worker 
437*1c60b9acSAndroid Build Coastguard Worker 		lwsl_parser("spill on %s\n", wsi->a.protocol->name);
438*1c60b9acSAndroid Build Coastguard Worker 
439*1c60b9acSAndroid Build Coastguard Worker 		switch (wsi->ws->opcode) {
440*1c60b9acSAndroid Build Coastguard Worker 		case LWSWSOPC_CLOSE:
441*1c60b9acSAndroid Build Coastguard Worker 
442*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->ws->peer_has_sent_close)
443*1c60b9acSAndroid Build Coastguard Worker 				break;
444*1c60b9acSAndroid Build Coastguard Worker 
445*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->peer_has_sent_close = 1;
446*1c60b9acSAndroid Build Coastguard Worker 
447*1c60b9acSAndroid Build Coastguard Worker 			pp = &wsi->ws->rx_ubuf[LWS_PRE];
448*1c60b9acSAndroid Build Coastguard Worker 			if (lws_check_opt(wsi->a.context->options,
449*1c60b9acSAndroid Build Coastguard Worker 					  LWS_SERVER_OPTION_VALIDATE_UTF8) &&
450*1c60b9acSAndroid Build Coastguard Worker 			    wsi->ws->rx_ubuf_head > 2 &&
451*1c60b9acSAndroid Build Coastguard Worker 			    lws_check_utf8(&wsi->ws->utf8, pp + 2,
452*1c60b9acSAndroid Build Coastguard Worker 					   wsi->ws->rx_ubuf_head - 2))
453*1c60b9acSAndroid Build Coastguard Worker 				goto utf8_fail;
454*1c60b9acSAndroid Build Coastguard Worker 
455*1c60b9acSAndroid Build Coastguard Worker 			/* is this an acknowledgment of our close? */
456*1c60b9acSAndroid Build Coastguard Worker 			if (lwsi_state(wsi) == LRS_AWAITING_CLOSE_ACK) {
457*1c60b9acSAndroid Build Coastguard Worker 				/*
458*1c60b9acSAndroid Build Coastguard Worker 				 * fine he has told us he is closing too, let's
459*1c60b9acSAndroid Build Coastguard Worker 				 * finish our close
460*1c60b9acSAndroid Build Coastguard Worker 				 */
461*1c60b9acSAndroid Build Coastguard Worker 				lwsl_parser("seen client close ack\n");
462*1c60b9acSAndroid Build Coastguard Worker 				return -1;
463*1c60b9acSAndroid Build Coastguard Worker 			}
464*1c60b9acSAndroid Build Coastguard Worker 			if (lwsi_state(wsi) == LRS_RETURNED_CLOSE)
465*1c60b9acSAndroid Build Coastguard Worker 				/* if he sends us 2 CLOSE, kill him */
466*1c60b9acSAndroid Build Coastguard Worker 				return -1;
467*1c60b9acSAndroid Build Coastguard Worker 
468*1c60b9acSAndroid Build Coastguard Worker 			if (lws_partial_buffered(wsi)) {
469*1c60b9acSAndroid Build Coastguard Worker 				/*
470*1c60b9acSAndroid Build Coastguard Worker 				 * if we're in the middle of something,
471*1c60b9acSAndroid Build Coastguard Worker 				 * we can't do a normal close response and
472*1c60b9acSAndroid Build Coastguard Worker 				 * have to just close our end.
473*1c60b9acSAndroid Build Coastguard Worker 				 */
474*1c60b9acSAndroid Build Coastguard Worker 				wsi->socket_is_permanently_unusable = 1;
475*1c60b9acSAndroid Build Coastguard Worker 				lwsl_parser("Closing on peer close "
476*1c60b9acSAndroid Build Coastguard Worker 					    "due to pending tx\n");
477*1c60b9acSAndroid Build Coastguard Worker 				return -1;
478*1c60b9acSAndroid Build Coastguard Worker 			}
479*1c60b9acSAndroid Build Coastguard Worker 
480*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->ws->rx_ubuf_head >= 2) {
481*1c60b9acSAndroid Build Coastguard Worker 				close_code = (unsigned short)((pp[0] << 8) | pp[1]);
482*1c60b9acSAndroid Build Coastguard Worker 				if (close_code < 1000 ||
483*1c60b9acSAndroid Build Coastguard Worker 				    close_code == 1004 ||
484*1c60b9acSAndroid Build Coastguard Worker 				    close_code == 1005 ||
485*1c60b9acSAndroid Build Coastguard Worker 				    close_code == 1006 ||
486*1c60b9acSAndroid Build Coastguard Worker 				    close_code == 1012 ||
487*1c60b9acSAndroid Build Coastguard Worker 				    close_code == 1013 ||
488*1c60b9acSAndroid Build Coastguard Worker 				    close_code == 1014 ||
489*1c60b9acSAndroid Build Coastguard Worker 				    close_code == 1015 ||
490*1c60b9acSAndroid Build Coastguard Worker 				    (close_code >= 1016 && close_code < 3000)
491*1c60b9acSAndroid Build Coastguard Worker 				) {
492*1c60b9acSAndroid Build Coastguard Worker 					pp[0] = (LWS_CLOSE_STATUS_PROTOCOL_ERR >> 8) & 0xff;
493*1c60b9acSAndroid Build Coastguard Worker 					pp[1] = LWS_CLOSE_STATUS_PROTOCOL_ERR & 0xff;
494*1c60b9acSAndroid Build Coastguard Worker 				}
495*1c60b9acSAndroid Build Coastguard Worker 			}
496*1c60b9acSAndroid Build Coastguard Worker 
497*1c60b9acSAndroid Build Coastguard Worker 			if (user_callback_handle_rxflow(
498*1c60b9acSAndroid Build Coastguard Worker 					wsi->a.protocol->callback, wsi,
499*1c60b9acSAndroid Build Coastguard Worker 					LWS_CALLBACK_WS_PEER_INITIATED_CLOSE,
500*1c60b9acSAndroid Build Coastguard Worker 					wsi->user_space,
501*1c60b9acSAndroid Build Coastguard Worker 					&wsi->ws->rx_ubuf[LWS_PRE],
502*1c60b9acSAndroid Build Coastguard Worker 					wsi->ws->rx_ubuf_head))
503*1c60b9acSAndroid Build Coastguard Worker 				return -1;
504*1c60b9acSAndroid Build Coastguard Worker 
505*1c60b9acSAndroid Build Coastguard Worker 			lwsl_parser("server sees client close packet\n");
506*1c60b9acSAndroid Build Coastguard Worker 			lwsi_set_state(wsi, LRS_RETURNED_CLOSE);
507*1c60b9acSAndroid Build Coastguard Worker 			/* deal with the close packet contents as a PONG */
508*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->payload_is_close = 1;
509*1c60b9acSAndroid Build Coastguard Worker 			goto process_as_ping;
510*1c60b9acSAndroid Build Coastguard Worker 
511*1c60b9acSAndroid Build Coastguard Worker 		case LWSWSOPC_PING:
512*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("received %d byte ping, sending pong\n",
513*1c60b9acSAndroid Build Coastguard Worker 						 (int)wsi->ws->rx_ubuf_head);
514*1c60b9acSAndroid Build Coastguard Worker 
515*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->ws->pong_pending_flag) {
516*1c60b9acSAndroid Build Coastguard Worker 				/*
517*1c60b9acSAndroid Build Coastguard Worker 				 * there is already a pending pong payload
518*1c60b9acSAndroid Build Coastguard Worker 				 * we should just log and drop
519*1c60b9acSAndroid Build Coastguard Worker 				 */
520*1c60b9acSAndroid Build Coastguard Worker 				lwsl_parser("DROP PING since one pending\n");
521*1c60b9acSAndroid Build Coastguard Worker 				goto ping_drop;
522*1c60b9acSAndroid Build Coastguard Worker 			}
523*1c60b9acSAndroid Build Coastguard Worker process_as_ping:
524*1c60b9acSAndroid Build Coastguard Worker 			/* control packets can only be < 128 bytes long */
525*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->ws->rx_ubuf_head > 128 - 3) {
526*1c60b9acSAndroid Build Coastguard Worker 				lwsl_parser("DROP PING payload too large\n");
527*1c60b9acSAndroid Build Coastguard Worker 				goto ping_drop;
528*1c60b9acSAndroid Build Coastguard Worker 			}
529*1c60b9acSAndroid Build Coastguard Worker 
530*1c60b9acSAndroid Build Coastguard Worker 			/* stash the pong payload */
531*1c60b9acSAndroid Build Coastguard Worker 			memcpy(wsi->ws->pong_payload_buf + LWS_PRE,
532*1c60b9acSAndroid Build Coastguard Worker 			       &wsi->ws->rx_ubuf[LWS_PRE],
533*1c60b9acSAndroid Build Coastguard Worker 				wsi->ws->rx_ubuf_head);
534*1c60b9acSAndroid Build Coastguard Worker 
535*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->pong_payload_len = (uint8_t)wsi->ws->rx_ubuf_head;
536*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->pong_pending_flag = 1;
537*1c60b9acSAndroid Build Coastguard Worker 
538*1c60b9acSAndroid Build Coastguard Worker 			/* get it sent as soon as possible */
539*1c60b9acSAndroid Build Coastguard Worker 			lws_callback_on_writable(wsi);
540*1c60b9acSAndroid Build Coastguard Worker ping_drop:
541*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->rx_ubuf_head = 0;
542*1c60b9acSAndroid Build Coastguard Worker 			return 0;
543*1c60b9acSAndroid Build Coastguard Worker 
544*1c60b9acSAndroid Build Coastguard Worker 		case LWSWSOPC_PONG:
545*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("received pong\n");
546*1c60b9acSAndroid Build Coastguard Worker 			lwsl_hexdump(&wsi->ws->rx_ubuf[LWS_PRE],
547*1c60b9acSAndroid Build Coastguard Worker 			             wsi->ws->rx_ubuf_head);
548*1c60b9acSAndroid Build Coastguard Worker 
549*1c60b9acSAndroid Build Coastguard Worker 			lws_validity_confirmed(wsi);
550*1c60b9acSAndroid Build Coastguard Worker 
551*1c60b9acSAndroid Build Coastguard Worker 			/* issue it */
552*1c60b9acSAndroid Build Coastguard Worker 			callback_action = LWS_CALLBACK_RECEIVE_PONG;
553*1c60b9acSAndroid Build Coastguard Worker 			break;
554*1c60b9acSAndroid Build Coastguard Worker 
555*1c60b9acSAndroid Build Coastguard Worker 		case LWSWSOPC_TEXT_FRAME:
556*1c60b9acSAndroid Build Coastguard Worker 		case LWSWSOPC_BINARY_FRAME:
557*1c60b9acSAndroid Build Coastguard Worker 		case LWSWSOPC_CONTINUATION:
558*1c60b9acSAndroid Build Coastguard Worker 			break;
559*1c60b9acSAndroid Build Coastguard Worker 
560*1c60b9acSAndroid Build Coastguard Worker 		default:
561*1c60b9acSAndroid Build Coastguard Worker 			lwsl_parser("unknown opc %x\n", wsi->ws->opcode);
562*1c60b9acSAndroid Build Coastguard Worker 
563*1c60b9acSAndroid Build Coastguard Worker 			return -1;
564*1c60b9acSAndroid Build Coastguard Worker 		}
565*1c60b9acSAndroid Build Coastguard Worker 
566*1c60b9acSAndroid Build Coastguard Worker 		/*
567*1c60b9acSAndroid Build Coastguard Worker 		 * No it's real payload, pass it up to the user callback.
568*1c60b9acSAndroid Build Coastguard Worker 		 *
569*1c60b9acSAndroid Build Coastguard Worker 		 * We have been statefully collecting it in the
570*1c60b9acSAndroid Build Coastguard Worker 		 * LWS_RXPS_WS_FRAME_PAYLOAD clause above.
571*1c60b9acSAndroid Build Coastguard Worker 		 *
572*1c60b9acSAndroid Build Coastguard Worker 		 * It's nicely buffered with the pre-padding taken care of
573*1c60b9acSAndroid Build Coastguard Worker 		 * so it can be sent straight out again using lws_write.
574*1c60b9acSAndroid Build Coastguard Worker 		 *
575*1c60b9acSAndroid Build Coastguard Worker 		 * However, now we have a chunk of it, we want to deal with it
576*1c60b9acSAndroid Build Coastguard Worker 		 * all here.  Since this may be input to permessage-deflate and
577*1c60b9acSAndroid Build Coastguard Worker 		 * there are block limits on that for input and output, we may
578*1c60b9acSAndroid Build Coastguard Worker 		 * need to iterate.
579*1c60b9acSAndroid Build Coastguard Worker 		 */
580*1c60b9acSAndroid Build Coastguard Worker 
581*1c60b9acSAndroid Build Coastguard Worker 		pmdrx.eb_in.token = &wsi->ws->rx_ubuf[LWS_PRE];
582*1c60b9acSAndroid Build Coastguard Worker 		pmdrx.eb_in.len = (int)wsi->ws->rx_ubuf_head;
583*1c60b9acSAndroid Build Coastguard Worker 
584*1c60b9acSAndroid Build Coastguard Worker 		/* for the non-pm-deflate case */
585*1c60b9acSAndroid Build Coastguard Worker 
586*1c60b9acSAndroid Build Coastguard Worker 		pmdrx.eb_out = pmdrx.eb_in;
587*1c60b9acSAndroid Build Coastguard Worker 
588*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->ws->opcode == LWSWSOPC_PONG && !pmdrx.eb_in.len)
589*1c60b9acSAndroid Build Coastguard Worker 			goto already_done;
590*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
591*1c60b9acSAndroid Build Coastguard Worker drain_extension:
592*1c60b9acSAndroid Build Coastguard Worker #endif
593*1c60b9acSAndroid Build Coastguard Worker 
594*1c60b9acSAndroid Build Coastguard Worker 		do {
595*1c60b9acSAndroid Build Coastguard Worker 
596*1c60b9acSAndroid Build Coastguard Worker //			lwsl_notice("%s: pmdrx.eb_in.len: %d\n", __func__,
597*1c60b9acSAndroid Build Coastguard Worker //					(int)pmdrx.eb_in.len);
598*1c60b9acSAndroid Build Coastguard Worker 
599*1c60b9acSAndroid Build Coastguard Worker 			if (lwsi_state(wsi) == LRS_RETURNED_CLOSE ||
600*1c60b9acSAndroid Build Coastguard Worker 			    lwsi_state(wsi) == LRS_AWAITING_CLOSE_ACK)
601*1c60b9acSAndroid Build Coastguard Worker 				goto already_done;
602*1c60b9acSAndroid Build Coastguard Worker 
603*1c60b9acSAndroid Build Coastguard Worker 			n = PMDR_DID_NOTHING;
604*1c60b9acSAndroid Build Coastguard Worker 
605*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
606*1c60b9acSAndroid Build Coastguard Worker 			lin = pmdrx.eb_in.len;
607*1c60b9acSAndroid Build Coastguard Worker 			//if (lin)
608*1c60b9acSAndroid Build Coastguard Worker 			//	lwsl_hexdump_notice(ebuf.token, ebuf.len);
609*1c60b9acSAndroid Build Coastguard Worker 			lwsl_ext("%s: +++ passing %d %p to ext\n", __func__,
610*1c60b9acSAndroid Build Coastguard Worker 					pmdrx.eb_in.len, pmdrx.eb_in.token);
611*1c60b9acSAndroid Build Coastguard Worker 
612*1c60b9acSAndroid Build Coastguard Worker 			n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &pmdrx, 0);
613*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("%s: ext says %d / ebuf.len %d\n", __func__,
614*1c60b9acSAndroid Build Coastguard Worker 				   n, pmdrx.eb_out.len);
615*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->ws->rx_draining_ext)
616*1c60b9acSAndroid Build Coastguard Worker 				already_processed &= (char)~ALREADY_PROCESSED_NO_CB;
617*1c60b9acSAndroid Build Coastguard Worker #endif
618*1c60b9acSAndroid Build Coastguard Worker 
619*1c60b9acSAndroid Build Coastguard Worker 			/*
620*1c60b9acSAndroid Build Coastguard Worker 			 * ebuf may be pointing somewhere completely different
621*1c60b9acSAndroid Build Coastguard Worker 			 * now, it's the output
622*1c60b9acSAndroid Build Coastguard Worker 			 */
623*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
624*1c60b9acSAndroid Build Coastguard Worker 			if (n < 0) {
625*1c60b9acSAndroid Build Coastguard Worker 				/*
626*1c60b9acSAndroid Build Coastguard Worker 				 * we may rely on this to get RX, just drop
627*1c60b9acSAndroid Build Coastguard Worker 				 * connection
628*1c60b9acSAndroid Build Coastguard Worker 				 */
629*1c60b9acSAndroid Build Coastguard Worker 				wsi->socket_is_permanently_unusable = 1;
630*1c60b9acSAndroid Build Coastguard Worker 				return -1;
631*1c60b9acSAndroid Build Coastguard Worker 			}
632*1c60b9acSAndroid Build Coastguard Worker 			if (n == PMDR_DID_NOTHING)
633*1c60b9acSAndroid Build Coastguard Worker 				/* ie, not PMDR_NOTHING_WE_SHOULD_DO */
634*1c60b9acSAndroid Build Coastguard Worker 				break;
635*1c60b9acSAndroid Build Coastguard Worker #endif
636*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("%s: post ext ret %d, ebuf in %d / out %d\n",
637*1c60b9acSAndroid Build Coastguard Worker 				    __func__, n, pmdrx.eb_in.len,
638*1c60b9acSAndroid Build Coastguard Worker 				    pmdrx.eb_out.len);
639*1c60b9acSAndroid Build Coastguard Worker 
640*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
641*1c60b9acSAndroid Build Coastguard Worker 			if (rx_draining_ext && !pmdrx.eb_out.len) {
642*1c60b9acSAndroid Build Coastguard Worker 				lwsl_debug("   --- ending drain on 0 read\n");
643*1c60b9acSAndroid Build Coastguard Worker 				goto already_done;
644*1c60b9acSAndroid Build Coastguard Worker 			}
645*1c60b9acSAndroid Build Coastguard Worker 
646*1c60b9acSAndroid Build Coastguard Worker 			if (n == PMDR_HAS_PENDING)
647*1c60b9acSAndroid Build Coastguard Worker 				/*
648*1c60b9acSAndroid Build Coastguard Worker 				 * extension had more...
649*1c60b9acSAndroid Build Coastguard Worker 				 * main loop will come back
650*1c60b9acSAndroid Build Coastguard Worker 				 */
651*1c60b9acSAndroid Build Coastguard Worker 				lws_add_wsi_to_draining_ext_list(wsi);
652*1c60b9acSAndroid Build Coastguard Worker 			else
653*1c60b9acSAndroid Build Coastguard Worker 				lws_remove_wsi_from_draining_ext_list(wsi);
654*1c60b9acSAndroid Build Coastguard Worker 
655*1c60b9acSAndroid Build Coastguard Worker 			rx_draining_ext = wsi->ws->rx_draining_ext;
656*1c60b9acSAndroid Build Coastguard Worker #endif
657*1c60b9acSAndroid Build Coastguard Worker 
658*1c60b9acSAndroid Build Coastguard Worker 			if (pmdrx.eb_out.len &&
659*1c60b9acSAndroid Build Coastguard Worker 			    wsi->ws->check_utf8 && !wsi->ws->defeat_check_utf8) {
660*1c60b9acSAndroid Build Coastguard Worker 				if (lws_check_utf8(&wsi->ws->utf8,
661*1c60b9acSAndroid Build Coastguard Worker 						   pmdrx.eb_out.token,
662*1c60b9acSAndroid Build Coastguard Worker 						   (size_t)pmdrx.eb_out.len)) {
663*1c60b9acSAndroid Build Coastguard Worker 					lws_close_reason(wsi,
664*1c60b9acSAndroid Build Coastguard Worker 						LWS_CLOSE_STATUS_INVALID_PAYLOAD,
665*1c60b9acSAndroid Build Coastguard Worker 						(uint8_t *)"bad utf8", 8);
666*1c60b9acSAndroid Build Coastguard Worker 					goto utf8_fail;
667*1c60b9acSAndroid Build Coastguard Worker 				}
668*1c60b9acSAndroid Build Coastguard Worker 
669*1c60b9acSAndroid Build Coastguard Worker 				/* we are ending partway through utf-8 character? */
670*1c60b9acSAndroid Build Coastguard Worker 				if (!wsi->ws->rx_packet_length &&
671*1c60b9acSAndroid Build Coastguard Worker 				    wsi->ws->final && wsi->ws->utf8
672*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
673*1c60b9acSAndroid Build Coastguard Worker 				    /* if ext not negotiated, going to be UNKNOWN */
674*1c60b9acSAndroid Build Coastguard Worker 				    && (n == PMDR_EMPTY_FINAL || n == PMDR_UNKNOWN)
675*1c60b9acSAndroid Build Coastguard Worker #endif
676*1c60b9acSAndroid Build Coastguard Worker 				) {
677*1c60b9acSAndroid Build Coastguard Worker 					lwsl_info("FINAL utf8 error\n");
678*1c60b9acSAndroid Build Coastguard Worker 					lws_close_reason(wsi,
679*1c60b9acSAndroid Build Coastguard Worker 						LWS_CLOSE_STATUS_INVALID_PAYLOAD,
680*1c60b9acSAndroid Build Coastguard Worker 						(uint8_t *)"partial utf8", 12);
681*1c60b9acSAndroid Build Coastguard Worker utf8_fail:
682*1c60b9acSAndroid Build Coastguard Worker 					lwsl_notice("utf8 error\n");
683*1c60b9acSAndroid Build Coastguard Worker 					lwsl_hexdump_notice(pmdrx.eb_out.token,
684*1c60b9acSAndroid Build Coastguard Worker 							    (size_t)pmdrx.eb_out.len);
685*1c60b9acSAndroid Build Coastguard Worker 
686*1c60b9acSAndroid Build Coastguard Worker 					return -1;
687*1c60b9acSAndroid Build Coastguard Worker 				}
688*1c60b9acSAndroid Build Coastguard Worker 			}
689*1c60b9acSAndroid Build Coastguard Worker 
690*1c60b9acSAndroid Build Coastguard Worker 			/* if pmd not enabled, in == out */
691*1c60b9acSAndroid Build Coastguard Worker 
692*1c60b9acSAndroid Build Coastguard Worker 			if (n == PMDR_DID_NOTHING
693*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
694*1c60b9acSAndroid Build Coastguard Worker 					||
695*1c60b9acSAndroid Build Coastguard Worker 			    n == PMDR_NOTHING_WE_SHOULD_DO ||
696*1c60b9acSAndroid Build Coastguard Worker 			    n == PMDR_UNKNOWN
697*1c60b9acSAndroid Build Coastguard Worker #endif
698*1c60b9acSAndroid Build Coastguard Worker 			    )
699*1c60b9acSAndroid Build Coastguard Worker 				pmdrx.eb_in.len -= pmdrx.eb_out.len;
700*1c60b9acSAndroid Build Coastguard Worker 
701*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->wsistate_pre_close &&
702*1c60b9acSAndroid Build Coastguard Worker 			    (pmdrx.eb_out.len >= 0 ||
703*1c60b9acSAndroid Build Coastguard Worker 			     callback_action == LWS_CALLBACK_RECEIVE_PONG ||
704*1c60b9acSAndroid Build Coastguard Worker 						       n == PMDR_EMPTY_FINAL)) {
705*1c60b9acSAndroid Build Coastguard Worker 				if (pmdrx.eb_out.len)
706*1c60b9acSAndroid Build Coastguard Worker 					pmdrx.eb_out.token[pmdrx.eb_out.len] = '\0';
707*1c60b9acSAndroid Build Coastguard Worker 
708*1c60b9acSAndroid Build Coastguard Worker 				if (wsi->a.protocol->callback &&
709*1c60b9acSAndroid Build Coastguard Worker 				    !(already_processed & ALREADY_PROCESSED_NO_CB)) {
710*1c60b9acSAndroid Build Coastguard Worker 					if (callback_action ==
711*1c60b9acSAndroid Build Coastguard Worker 						      LWS_CALLBACK_RECEIVE_PONG)
712*1c60b9acSAndroid Build Coastguard Worker 						lwsl_info("Doing pong callback\n");
713*1c60b9acSAndroid Build Coastguard Worker 
714*1c60b9acSAndroid Build Coastguard Worker 					ret = user_callback_handle_rxflow(
715*1c60b9acSAndroid Build Coastguard Worker 						wsi->a.protocol->callback, wsi,
716*1c60b9acSAndroid Build Coastguard Worker 						(enum lws_callback_reasons)
717*1c60b9acSAndroid Build Coastguard Worker 							     callback_action,
718*1c60b9acSAndroid Build Coastguard Worker 						wsi->user_space,
719*1c60b9acSAndroid Build Coastguard Worker 						pmdrx.eb_out.token,
720*1c60b9acSAndroid Build Coastguard Worker 						(size_t)pmdrx.eb_out.len);
721*1c60b9acSAndroid Build Coastguard Worker 				}
722*1c60b9acSAndroid Build Coastguard Worker 				wsi->ws->first_fragment = 0;
723*1c60b9acSAndroid Build Coastguard Worker 			}
724*1c60b9acSAndroid Build Coastguard Worker 
725*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
726*1c60b9acSAndroid Build Coastguard Worker 			if (!lin)
727*1c60b9acSAndroid Build Coastguard Worker 				break;
728*1c60b9acSAndroid Build Coastguard Worker #endif
729*1c60b9acSAndroid Build Coastguard Worker 
730*1c60b9acSAndroid Build Coastguard Worker 		} while (pmdrx.eb_in.len
731*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
732*1c60b9acSAndroid Build Coastguard Worker 				|| rx_draining_ext
733*1c60b9acSAndroid Build Coastguard Worker #endif
734*1c60b9acSAndroid Build Coastguard Worker 		);
735*1c60b9acSAndroid Build Coastguard Worker 
736*1c60b9acSAndroid Build Coastguard Worker already_done:
737*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->rx_ubuf_head = 0;
738*1c60b9acSAndroid Build Coastguard Worker 		break;
739*1c60b9acSAndroid Build Coastguard Worker 	}
740*1c60b9acSAndroid Build Coastguard Worker 
741*1c60b9acSAndroid Build Coastguard Worker 	return ret;
742*1c60b9acSAndroid Build Coastguard Worker 
743*1c60b9acSAndroid Build Coastguard Worker illegal_ctl_length:
744*1c60b9acSAndroid Build Coastguard Worker 
745*1c60b9acSAndroid Build Coastguard Worker 	lwsl_warn("Control frame with xtended length is illegal\n");
746*1c60b9acSAndroid Build Coastguard Worker 	/* kill the connection */
747*1c60b9acSAndroid Build Coastguard Worker 	return -1;
748*1c60b9acSAndroid Build Coastguard Worker }
749*1c60b9acSAndroid Build Coastguard Worker 
750*1c60b9acSAndroid Build Coastguard Worker 
751*1c60b9acSAndroid Build Coastguard Worker size_t
lws_remaining_packet_payload(struct lws * wsi)752*1c60b9acSAndroid Build Coastguard Worker lws_remaining_packet_payload(struct lws *wsi)
753*1c60b9acSAndroid Build Coastguard Worker {
754*1c60b9acSAndroid Build Coastguard Worker 	return wsi->ws->rx_packet_length;
755*1c60b9acSAndroid Build Coastguard Worker }
756*1c60b9acSAndroid Build Coastguard Worker 
lws_frame_is_binary(struct lws * wsi)757*1c60b9acSAndroid Build Coastguard Worker int lws_frame_is_binary(struct lws *wsi)
758*1c60b9acSAndroid Build Coastguard Worker {
759*1c60b9acSAndroid Build Coastguard Worker 	return wsi->ws->frame_is_binary;
760*1c60b9acSAndroid Build Coastguard Worker }
761*1c60b9acSAndroid Build Coastguard Worker 
762*1c60b9acSAndroid Build Coastguard Worker void
lws_add_wsi_to_draining_ext_list(struct lws * wsi)763*1c60b9acSAndroid Build Coastguard Worker lws_add_wsi_to_draining_ext_list(struct lws *wsi)
764*1c60b9acSAndroid Build Coastguard Worker {
765*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
766*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
767*1c60b9acSAndroid Build Coastguard Worker 
768*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->ws->rx_draining_ext)
769*1c60b9acSAndroid Build Coastguard Worker 		return;
770*1c60b9acSAndroid Build Coastguard Worker 
771*1c60b9acSAndroid Build Coastguard Worker 	lwsl_debug("%s: RX EXT DRAINING: Adding to list\n", __func__);
772*1c60b9acSAndroid Build Coastguard Worker 
773*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->rx_draining_ext = 1;
774*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->rx_draining_ext_list = pt->ws.rx_draining_ext_list;
775*1c60b9acSAndroid Build Coastguard Worker 	pt->ws.rx_draining_ext_list = wsi;
776*1c60b9acSAndroid Build Coastguard Worker #endif
777*1c60b9acSAndroid Build Coastguard Worker }
778*1c60b9acSAndroid Build Coastguard Worker 
779*1c60b9acSAndroid Build Coastguard Worker void
lws_remove_wsi_from_draining_ext_list(struct lws * wsi)780*1c60b9acSAndroid Build Coastguard Worker lws_remove_wsi_from_draining_ext_list(struct lws *wsi)
781*1c60b9acSAndroid Build Coastguard Worker {
782*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
783*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
784*1c60b9acSAndroid Build Coastguard Worker 	struct lws **w = &pt->ws.rx_draining_ext_list;
785*1c60b9acSAndroid Build Coastguard Worker 
786*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->ws->rx_draining_ext)
787*1c60b9acSAndroid Build Coastguard Worker 		return;
788*1c60b9acSAndroid Build Coastguard Worker 
789*1c60b9acSAndroid Build Coastguard Worker 	lwsl_debug("%s: RX EXT DRAINING: Removing from list\n", __func__);
790*1c60b9acSAndroid Build Coastguard Worker 
791*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->rx_draining_ext = 0;
792*1c60b9acSAndroid Build Coastguard Worker 
793*1c60b9acSAndroid Build Coastguard Worker 	/* remove us from context draining ext list */
794*1c60b9acSAndroid Build Coastguard Worker 	while (*w) {
795*1c60b9acSAndroid Build Coastguard Worker 		if (*w == wsi) {
796*1c60b9acSAndroid Build Coastguard Worker 			/* if us, point it instead to who we were pointing to */
797*1c60b9acSAndroid Build Coastguard Worker 			*w = wsi->ws->rx_draining_ext_list;
798*1c60b9acSAndroid Build Coastguard Worker 			break;
799*1c60b9acSAndroid Build Coastguard Worker 		}
800*1c60b9acSAndroid Build Coastguard Worker 		w = &((*w)->ws->rx_draining_ext_list);
801*1c60b9acSAndroid Build Coastguard Worker 	}
802*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->rx_draining_ext_list = NULL;
803*1c60b9acSAndroid Build Coastguard Worker #endif
804*1c60b9acSAndroid Build Coastguard Worker }
805*1c60b9acSAndroid Build Coastguard Worker 
806*1c60b9acSAndroid Build Coastguard Worker static int
lws_0405_frame_mask_generate(struct lws * wsi)807*1c60b9acSAndroid Build Coastguard Worker lws_0405_frame_mask_generate(struct lws *wsi)
808*1c60b9acSAndroid Build Coastguard Worker {
809*1c60b9acSAndroid Build Coastguard Worker 	size_t n;
810*1c60b9acSAndroid Build Coastguard Worker 	/* fetch the per-frame nonce */
811*1c60b9acSAndroid Build Coastguard Worker 
812*1c60b9acSAndroid Build Coastguard Worker 	n = lws_get_random(lws_get_context(wsi), wsi->ws->mask, 4);
813*1c60b9acSAndroid Build Coastguard Worker 	if (n != 4) {
814*1c60b9acSAndroid Build Coastguard Worker 		lwsl_parser("Unable to read from random device %s %d\n",
815*1c60b9acSAndroid Build Coastguard Worker 			    SYSTEM_RANDOM_FILEPATH, (int)n);
816*1c60b9acSAndroid Build Coastguard Worker 		return 1;
817*1c60b9acSAndroid Build Coastguard Worker 	}
818*1c60b9acSAndroid Build Coastguard Worker 
819*1c60b9acSAndroid Build Coastguard Worker 	/* start masking from first byte of masking key buffer */
820*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->mask_idx = 0;
821*1c60b9acSAndroid Build Coastguard Worker 
822*1c60b9acSAndroid Build Coastguard Worker 	return 0;
823*1c60b9acSAndroid Build Coastguard Worker }
824*1c60b9acSAndroid Build Coastguard Worker 
825*1c60b9acSAndroid Build Coastguard Worker int
lws_server_init_wsi_for_ws(struct lws * wsi)826*1c60b9acSAndroid Build Coastguard Worker lws_server_init_wsi_for_ws(struct lws *wsi)
827*1c60b9acSAndroid Build Coastguard Worker {
828*1c60b9acSAndroid Build Coastguard Worker 	int n;
829*1c60b9acSAndroid Build Coastguard Worker 
830*1c60b9acSAndroid Build Coastguard Worker 	lwsi_set_state(wsi, LRS_ESTABLISHED);
831*1c60b9acSAndroid Build Coastguard Worker 
832*1c60b9acSAndroid Build Coastguard Worker 	/*
833*1c60b9acSAndroid Build Coastguard Worker 	 * create the frame buffer for this connection according to the
834*1c60b9acSAndroid Build Coastguard Worker 	 * size mentioned in the protocol definition.  If 0 there, use
835*1c60b9acSAndroid Build Coastguard Worker 	 * a big default for compatibility
836*1c60b9acSAndroid Build Coastguard Worker 	 */
837*1c60b9acSAndroid Build Coastguard Worker 
838*1c60b9acSAndroid Build Coastguard Worker 	n = (int)wsi->a.protocol->rx_buffer_size;
839*1c60b9acSAndroid Build Coastguard Worker 	if (!n)
840*1c60b9acSAndroid Build Coastguard Worker 		n = (int)wsi->a.context->pt_serv_buf_size;
841*1c60b9acSAndroid Build Coastguard Worker 	n += LWS_PRE;
842*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->rx_ubuf = lws_malloc((unsigned int)n + 4 /* 0x0000ffff zlib */, "rx_ubuf");
843*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->ws->rx_ubuf) {
844*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("Out of Mem allocating rx buffer %d\n", n);
845*1c60b9acSAndroid Build Coastguard Worker 		return 1;
846*1c60b9acSAndroid Build Coastguard Worker 	}
847*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->rx_ubuf_alloc = (uint32_t)n;
848*1c60b9acSAndroid Build Coastguard Worker 
849*1c60b9acSAndroid Build Coastguard Worker 	/* notify user code that we're ready to roll */
850*1c60b9acSAndroid Build Coastguard Worker 
851*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->a.protocol->callback)
852*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED,
853*1c60b9acSAndroid Build Coastguard Worker 					    wsi->user_space,
854*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_TLS
855*1c60b9acSAndroid Build Coastguard Worker 					    wsi->tls.ssl,
856*1c60b9acSAndroid Build Coastguard Worker #else
857*1c60b9acSAndroid Build Coastguard Worker 					    NULL,
858*1c60b9acSAndroid Build Coastguard Worker #endif
859*1c60b9acSAndroid Build Coastguard Worker 					    wsi->h2_stream_carries_ws))
860*1c60b9acSAndroid Build Coastguard Worker 			return 1;
861*1c60b9acSAndroid Build Coastguard Worker 
862*1c60b9acSAndroid Build Coastguard Worker 	lws_validity_confirmed(wsi);
863*1c60b9acSAndroid Build Coastguard Worker 	lwsl_debug("ws established\n");
864*1c60b9acSAndroid Build Coastguard Worker 
865*1c60b9acSAndroid Build Coastguard Worker 	return 0;
866*1c60b9acSAndroid Build Coastguard Worker }
867*1c60b9acSAndroid Build Coastguard Worker 
868*1c60b9acSAndroid Build Coastguard Worker 
869*1c60b9acSAndroid Build Coastguard Worker 
870*1c60b9acSAndroid Build Coastguard Worker int
lws_is_final_fragment(struct lws * wsi)871*1c60b9acSAndroid Build Coastguard Worker lws_is_final_fragment(struct lws *wsi)
872*1c60b9acSAndroid Build Coastguard Worker {
873*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
874*1c60b9acSAndroid Build Coastguard Worker 	lwsl_debug("%s: final %d, rx pk length %ld, draining %ld\n", __func__,
875*1c60b9acSAndroid Build Coastguard Worker 		   wsi->ws->final, (long)wsi->ws->rx_packet_length,
876*1c60b9acSAndroid Build Coastguard Worker 		   (long)wsi->ws->rx_draining_ext);
877*1c60b9acSAndroid Build Coastguard Worker 	return wsi->ws->final && !wsi->ws->rx_packet_length &&
878*1c60b9acSAndroid Build Coastguard Worker 	       !wsi->ws->rx_draining_ext;
879*1c60b9acSAndroid Build Coastguard Worker #else
880*1c60b9acSAndroid Build Coastguard Worker 	return wsi->ws->final && !wsi->ws->rx_packet_length;
881*1c60b9acSAndroid Build Coastguard Worker #endif
882*1c60b9acSAndroid Build Coastguard Worker }
883*1c60b9acSAndroid Build Coastguard Worker 
884*1c60b9acSAndroid Build Coastguard Worker int
lws_is_first_fragment(struct lws * wsi)885*1c60b9acSAndroid Build Coastguard Worker lws_is_first_fragment(struct lws *wsi)
886*1c60b9acSAndroid Build Coastguard Worker {
887*1c60b9acSAndroid Build Coastguard Worker 	return wsi->ws->first_fragment;
888*1c60b9acSAndroid Build Coastguard Worker }
889*1c60b9acSAndroid Build Coastguard Worker 
890*1c60b9acSAndroid Build Coastguard Worker unsigned char
lws_get_reserved_bits(struct lws * wsi)891*1c60b9acSAndroid Build Coastguard Worker lws_get_reserved_bits(struct lws *wsi)
892*1c60b9acSAndroid Build Coastguard Worker {
893*1c60b9acSAndroid Build Coastguard Worker 	return wsi->ws->rsv;
894*1c60b9acSAndroid Build Coastguard Worker }
895*1c60b9acSAndroid Build Coastguard Worker 
896*1c60b9acSAndroid Build Coastguard Worker int
lws_get_close_length(struct lws * wsi)897*1c60b9acSAndroid Build Coastguard Worker lws_get_close_length(struct lws *wsi)
898*1c60b9acSAndroid Build Coastguard Worker {
899*1c60b9acSAndroid Build Coastguard Worker 	return wsi->ws->close_in_ping_buffer_len;
900*1c60b9acSAndroid Build Coastguard Worker }
901*1c60b9acSAndroid Build Coastguard Worker 
902*1c60b9acSAndroid Build Coastguard Worker unsigned char *
lws_get_close_payload(struct lws * wsi)903*1c60b9acSAndroid Build Coastguard Worker lws_get_close_payload(struct lws *wsi)
904*1c60b9acSAndroid Build Coastguard Worker {
905*1c60b9acSAndroid Build Coastguard Worker 	return &wsi->ws->ping_payload_buf[LWS_PRE];
906*1c60b9acSAndroid Build Coastguard Worker }
907*1c60b9acSAndroid Build Coastguard Worker 
908*1c60b9acSAndroid Build Coastguard Worker void
lws_close_reason(struct lws * wsi,enum lws_close_status status,unsigned char * buf,size_t len)909*1c60b9acSAndroid Build Coastguard Worker lws_close_reason(struct lws *wsi, enum lws_close_status status,
910*1c60b9acSAndroid Build Coastguard Worker 		 unsigned char *buf, size_t len)
911*1c60b9acSAndroid Build Coastguard Worker {
912*1c60b9acSAndroid Build Coastguard Worker 	unsigned char *p, *start;
913*1c60b9acSAndroid Build Coastguard Worker 	int budget = sizeof(wsi->ws->ping_payload_buf) - LWS_PRE;
914*1c60b9acSAndroid Build Coastguard Worker 
915*1c60b9acSAndroid Build Coastguard Worker 	assert(lwsi_role_ws(wsi));
916*1c60b9acSAndroid Build Coastguard Worker 
917*1c60b9acSAndroid Build Coastguard Worker 	start = p = &wsi->ws->ping_payload_buf[LWS_PRE];
918*1c60b9acSAndroid Build Coastguard Worker 
919*1c60b9acSAndroid Build Coastguard Worker 	*p++ = (uint8_t)((((int)status) >> 8) & 0xff);
920*1c60b9acSAndroid Build Coastguard Worker 	*p++ = (uint8_t)(((int)status) & 0xff);
921*1c60b9acSAndroid Build Coastguard Worker 
922*1c60b9acSAndroid Build Coastguard Worker 	if (buf)
923*1c60b9acSAndroid Build Coastguard Worker 		while (len-- && p < start + budget)
924*1c60b9acSAndroid Build Coastguard Worker 			*p++ = *buf++;
925*1c60b9acSAndroid Build Coastguard Worker 
926*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->close_in_ping_buffer_len = (uint8_t)lws_ptr_diff(p, start);
927*1c60b9acSAndroid Build Coastguard Worker }
928*1c60b9acSAndroid Build Coastguard Worker 
929*1c60b9acSAndroid Build Coastguard Worker static int
lws_is_ws_with_ext(struct lws * wsi)930*1c60b9acSAndroid Build Coastguard Worker lws_is_ws_with_ext(struct lws *wsi)
931*1c60b9acSAndroid Build Coastguard Worker {
932*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITHOUT_EXTENSIONS)
933*1c60b9acSAndroid Build Coastguard Worker 	return 0;
934*1c60b9acSAndroid Build Coastguard Worker #else
935*1c60b9acSAndroid Build Coastguard Worker 	return lwsi_role_ws(wsi) && !!wsi->ws->count_act_ext;
936*1c60b9acSAndroid Build Coastguard Worker #endif
937*1c60b9acSAndroid Build Coastguard Worker }
938*1c60b9acSAndroid Build Coastguard Worker 
939*1c60b9acSAndroid Build Coastguard Worker static int
rops_handle_POLLIN_ws(struct lws_context_per_thread * pt,struct lws * wsi,struct lws_pollfd * pollfd)940*1c60b9acSAndroid Build Coastguard Worker rops_handle_POLLIN_ws(struct lws_context_per_thread *pt, struct lws *wsi,
941*1c60b9acSAndroid Build Coastguard Worker 		       struct lws_pollfd *pollfd)
942*1c60b9acSAndroid Build Coastguard Worker {
943*1c60b9acSAndroid Build Coastguard Worker 	unsigned int pending = 0;
944*1c60b9acSAndroid Build Coastguard Worker 	struct lws_tokens ebuf;
945*1c60b9acSAndroid Build Coastguard Worker 	char buffered = 0;
946*1c60b9acSAndroid Build Coastguard Worker 	int n = 0, m, sanity = 10;
947*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
948*1c60b9acSAndroid Build Coastguard Worker 	struct lws *wsi1;
949*1c60b9acSAndroid Build Coastguard Worker #endif
950*1c60b9acSAndroid Build Coastguard Worker 
951*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->ws) {
952*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("ws role wsi with no ws\n");
953*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_PLEASE_CLOSE_ME;
954*1c60b9acSAndroid Build Coastguard Worker 	}
955*1c60b9acSAndroid Build Coastguard Worker 
956*1c60b9acSAndroid Build Coastguard Worker 	// lwsl_notice("%s: %s\n", __func__, wsi->a.protocol->name);
957*1c60b9acSAndroid Build Coastguard Worker 
958*1c60b9acSAndroid Build Coastguard Worker 	//lwsl_info("%s: wsistate 0x%x, pollout %d\n", __func__,
959*1c60b9acSAndroid Build Coastguard Worker 	//	   wsi->wsistate, pollfd->revents & LWS_POLLOUT);
960*1c60b9acSAndroid Build Coastguard Worker 
961*1c60b9acSAndroid Build Coastguard Worker 	/*
962*1c60b9acSAndroid Build Coastguard Worker 	 * something went wrong with parsing the handshake, and
963*1c60b9acSAndroid Build Coastguard Worker 	 * we ended up back in the event loop without completing it
964*1c60b9acSAndroid Build Coastguard Worker 	 */
965*1c60b9acSAndroid Build Coastguard Worker 	if (lwsi_state(wsi) == LRS_PRE_WS_SERVING_ACCEPT) {
966*1c60b9acSAndroid Build Coastguard Worker 		wsi->socket_is_permanently_unusable = 1;
967*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_PLEASE_CLOSE_ME;
968*1c60b9acSAndroid Build Coastguard Worker 	}
969*1c60b9acSAndroid Build Coastguard Worker 
970*1c60b9acSAndroid Build Coastguard Worker 	ebuf.token = NULL;
971*1c60b9acSAndroid Build Coastguard Worker 	ebuf.len = 0;
972*1c60b9acSAndroid Build Coastguard Worker 
973*1c60b9acSAndroid Build Coastguard Worker 	if (lwsi_state(wsi) == LRS_WAITING_CONNECT) {
974*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
975*1c60b9acSAndroid Build Coastguard Worker 		if ((pollfd->revents & LWS_POLLOUT) &&
976*1c60b9acSAndroid Build Coastguard Worker 		    lws_handle_POLLOUT_event(wsi, pollfd)) {
977*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("POLLOUT event closed it\n");
978*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_PLEASE_CLOSE_ME;
979*1c60b9acSAndroid Build Coastguard Worker 		}
980*1c60b9acSAndroid Build Coastguard Worker 
981*1c60b9acSAndroid Build Coastguard Worker 		n = lws_http_client_socket_service(wsi, pollfd);
982*1c60b9acSAndroid Build Coastguard Worker 		if (n)
983*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_WSI_ALREADY_DIED;
984*1c60b9acSAndroid Build Coastguard Worker #endif
985*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_HANDLED;
986*1c60b9acSAndroid Build Coastguard Worker 	}
987*1c60b9acSAndroid Build Coastguard Worker 
988*1c60b9acSAndroid Build Coastguard Worker 	/* 1: something requested a callback when it was OK to write */
989*1c60b9acSAndroid Build Coastguard Worker 
990*1c60b9acSAndroid Build Coastguard Worker 	if ((pollfd->revents & LWS_POLLOUT) &&
991*1c60b9acSAndroid Build Coastguard Worker 	    lwsi_state_can_handle_POLLOUT(wsi) &&
992*1c60b9acSAndroid Build Coastguard Worker 	    lws_handle_POLLOUT_event(wsi, pollfd)) {
993*1c60b9acSAndroid Build Coastguard Worker 		if (lwsi_state(wsi) == LRS_RETURNED_CLOSE)
994*1c60b9acSAndroid Build Coastguard Worker 			lwsi_set_state(wsi, LRS_FLUSHING_BEFORE_CLOSE);
995*1c60b9acSAndroid Build Coastguard Worker 
996*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_PLEASE_CLOSE_ME;
997*1c60b9acSAndroid Build Coastguard Worker 	}
998*1c60b9acSAndroid Build Coastguard Worker 
999*1c60b9acSAndroid Build Coastguard Worker 	if (lwsi_state(wsi) == LRS_RETURNED_CLOSE ||
1000*1c60b9acSAndroid Build Coastguard Worker 	    lwsi_state(wsi) == LRS_WAITING_TO_SEND_CLOSE) {
1001*1c60b9acSAndroid Build Coastguard Worker 		/*
1002*1c60b9acSAndroid Build Coastguard Worker 		 * we stopped caring about anything except control
1003*1c60b9acSAndroid Build Coastguard Worker 		 * packets.  Force flow control off, defeat tx
1004*1c60b9acSAndroid Build Coastguard Worker 		 * draining.
1005*1c60b9acSAndroid Build Coastguard Worker 		 */
1006*1c60b9acSAndroid Build Coastguard Worker 		lws_rx_flow_control(wsi, 1);
1007*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
1008*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->ws)
1009*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->tx_draining_ext = 0;
1010*1c60b9acSAndroid Build Coastguard Worker #endif
1011*1c60b9acSAndroid Build Coastguard Worker 	}
1012*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
1013*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->ws->tx_draining_ext) {
1014*1c60b9acSAndroid Build Coastguard Worker 		lws_handle_POLLOUT_event(wsi, pollfd);
1015*1c60b9acSAndroid Build Coastguard Worker 		//lwsl_notice("%s: tx drain\n", __func__);
1016*1c60b9acSAndroid Build Coastguard Worker 		/*
1017*1c60b9acSAndroid Build Coastguard Worker 		 * We cannot deal with new RX until the TX ext path has
1018*1c60b9acSAndroid Build Coastguard Worker 		 * been drained.  It's because new rx will, eg, crap on
1019*1c60b9acSAndroid Build Coastguard Worker 		 * the wsi rx buf that may be needed to retain state.
1020*1c60b9acSAndroid Build Coastguard Worker 		 *
1021*1c60b9acSAndroid Build Coastguard Worker 		 * TX ext drain path MUST go through event loop to avoid
1022*1c60b9acSAndroid Build Coastguard Worker 		 * blocking.
1023*1c60b9acSAndroid Build Coastguard Worker 		 */
1024*1c60b9acSAndroid Build Coastguard Worker 		lws_callback_on_writable(wsi);
1025*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_HANDLED;
1026*1c60b9acSAndroid Build Coastguard Worker 	}
1027*1c60b9acSAndroid Build Coastguard Worker #endif
1028*1c60b9acSAndroid Build Coastguard Worker 	if ((pollfd->revents & LWS_POLLIN) && lws_is_flowcontrolled(wsi)) {
1029*1c60b9acSAndroid Build Coastguard Worker 		/* We cannot deal with any kind of new RX because we are
1030*1c60b9acSAndroid Build Coastguard Worker 		 * RX-flowcontrolled.
1031*1c60b9acSAndroid Build Coastguard Worker 		 */
1032*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: flowcontrolled, ignoring rx\n", __func__);
1033*1c60b9acSAndroid Build Coastguard Worker 
1034*1c60b9acSAndroid Build Coastguard Worker 		if (__lws_change_pollfd(wsi, LWS_POLLIN, 0))
1035*1c60b9acSAndroid Build Coastguard Worker 			return -1;
1036*1c60b9acSAndroid Build Coastguard Worker 
1037*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_HANDLED;
1038*1c60b9acSAndroid Build Coastguard Worker 	}
1039*1c60b9acSAndroid Build Coastguard Worker 
1040*1c60b9acSAndroid Build Coastguard Worker 	if (lws_is_flowcontrolled(wsi))
1041*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_HANDLED;
1042*1c60b9acSAndroid Build Coastguard Worker 
1043*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
1044*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->mux_substream || wsi->upgraded_to_http2) {
1045*1c60b9acSAndroid Build Coastguard Worker 		wsi1 = lws_get_network_wsi(wsi);
1046*1c60b9acSAndroid Build Coastguard Worker 		if (wsi1 && lws_has_buffered_out(wsi1))
1047*1c60b9acSAndroid Build Coastguard Worker 			/* We cannot deal with any kind of new RX
1048*1c60b9acSAndroid Build Coastguard Worker 			 * because we are dealing with a partial send
1049*1c60b9acSAndroid Build Coastguard Worker 			 * (new RX may trigger new http_action() that
1050*1c60b9acSAndroid Build Coastguard Worker 			 * expect to be able to send)
1051*1c60b9acSAndroid Build Coastguard Worker 			 */
1052*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_HANDLED;
1053*1c60b9acSAndroid Build Coastguard Worker 	}
1054*1c60b9acSAndroid Build Coastguard Worker #endif
1055*1c60b9acSAndroid Build Coastguard Worker 
1056*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
1057*1c60b9acSAndroid Build Coastguard Worker 	/* 2: RX Extension needs to be drained
1058*1c60b9acSAndroid Build Coastguard Worker 	 */
1059*1c60b9acSAndroid Build Coastguard Worker 
1060*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->ws->rx_draining_ext) {
1061*1c60b9acSAndroid Build Coastguard Worker 
1062*1c60b9acSAndroid Build Coastguard Worker 		lwsl_debug("%s: RX EXT DRAINING: Service\n", __func__);
1063*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
1064*1c60b9acSAndroid Build Coastguard Worker 		if (lwsi_role_client(wsi)) {
1065*1c60b9acSAndroid Build Coastguard Worker 			n = lws_ws_client_rx_sm(wsi, 0);
1066*1c60b9acSAndroid Build Coastguard Worker 			if (n < 0)
1067*1c60b9acSAndroid Build Coastguard Worker 				/* we closed wsi */
1068*1c60b9acSAndroid Build Coastguard Worker 				return LWS_HPI_RET_PLEASE_CLOSE_ME;
1069*1c60b9acSAndroid Build Coastguard Worker 		} else
1070*1c60b9acSAndroid Build Coastguard Worker #endif
1071*1c60b9acSAndroid Build Coastguard Worker 			n = lws_ws_rx_sm(wsi, ALREADY_PROCESSED_IGNORE_CHAR, 0);
1072*1c60b9acSAndroid Build Coastguard Worker 
1073*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_HANDLED;
1074*1c60b9acSAndroid Build Coastguard Worker 	}
1075*1c60b9acSAndroid Build Coastguard Worker 
1076*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->ws->rx_draining_ext)
1077*1c60b9acSAndroid Build Coastguard Worker 		/*
1078*1c60b9acSAndroid Build Coastguard Worker 		 * We have RX EXT content to drain, but can't do it
1079*1c60b9acSAndroid Build Coastguard Worker 		 * right now.  That means we cannot do anything lower
1080*1c60b9acSAndroid Build Coastguard Worker 		 * priority either.
1081*1c60b9acSAndroid Build Coastguard Worker 		 */
1082*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_HANDLED;
1083*1c60b9acSAndroid Build Coastguard Worker #endif
1084*1c60b9acSAndroid Build Coastguard Worker 
1085*1c60b9acSAndroid Build Coastguard Worker 	/* 3: buflist needs to be drained
1086*1c60b9acSAndroid Build Coastguard Worker 	 */
1087*1c60b9acSAndroid Build Coastguard Worker read:
1088*1c60b9acSAndroid Build Coastguard Worker 	//lws_buflist_describe(&wsi->buflist, wsi, __func__);
1089*1c60b9acSAndroid Build Coastguard Worker 	ebuf.len = (int)lws_buflist_next_segment_len(&wsi->buflist,
1090*1c60b9acSAndroid Build Coastguard Worker 						     &ebuf.token);
1091*1c60b9acSAndroid Build Coastguard Worker 	if (ebuf.len) {
1092*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("draining buflist (len %d)\n", ebuf.len);
1093*1c60b9acSAndroid Build Coastguard Worker 		buffered = 1;
1094*1c60b9acSAndroid Build Coastguard Worker 		goto drain;
1095*1c60b9acSAndroid Build Coastguard Worker 	}
1096*1c60b9acSAndroid Build Coastguard Worker 
1097*1c60b9acSAndroid Build Coastguard Worker 	if (!(pollfd->revents & pollfd->events & LWS_POLLIN) && !wsi->http.ah)
1098*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_HANDLED;
1099*1c60b9acSAndroid Build Coastguard Worker 
1100*1c60b9acSAndroid Build Coastguard Worker 	if (lws_is_flowcontrolled(wsi)) {
1101*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: %p should be rxflow (bm 0x%x)..\n",
1102*1c60b9acSAndroid Build Coastguard Worker 			    __func__, wsi, wsi->rxflow_bitmap);
1103*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HPI_RET_HANDLED;
1104*1c60b9acSAndroid Build Coastguard Worker 	}
1105*1c60b9acSAndroid Build Coastguard Worker 
1106*1c60b9acSAndroid Build Coastguard Worker 	if (!(lwsi_role_client(wsi) &&
1107*1c60b9acSAndroid Build Coastguard Worker 	      (lwsi_state(wsi) != LRS_ESTABLISHED &&
1108*1c60b9acSAndroid Build Coastguard Worker 	       lwsi_state(wsi) != LRS_AWAITING_CLOSE_ACK &&
1109*1c60b9acSAndroid Build Coastguard Worker 	       lwsi_state(wsi) != LRS_H2_WAITING_TO_SEND_HEADERS))) {
1110*1c60b9acSAndroid Build Coastguard Worker 		/*
1111*1c60b9acSAndroid Build Coastguard Worker 		 * In case we are going to react to this rx by scheduling
1112*1c60b9acSAndroid Build Coastguard Worker 		 * writes, we need to restrict the amount of rx to the size
1113*1c60b9acSAndroid Build Coastguard Worker 		 * the protocol reported for rx buffer.
1114*1c60b9acSAndroid Build Coastguard Worker 		 *
1115*1c60b9acSAndroid Build Coastguard Worker 		 * Otherwise we get a situation we have to absorb possibly a
1116*1c60b9acSAndroid Build Coastguard Worker 		 * lot of reads before we get a chance to drain them by writing
1117*1c60b9acSAndroid Build Coastguard Worker 		 * them, eg, with echo type tests in autobahn.
1118*1c60b9acSAndroid Build Coastguard Worker 		 */
1119*1c60b9acSAndroid Build Coastguard Worker 
1120*1c60b9acSAndroid Build Coastguard Worker 		buffered = 0;
1121*1c60b9acSAndroid Build Coastguard Worker 		ebuf.token = pt->serv_buf;
1122*1c60b9acSAndroid Build Coastguard Worker 		if (lwsi_role_ws(wsi))
1123*1c60b9acSAndroid Build Coastguard Worker 			ebuf.len = (int)wsi->ws->rx_ubuf_alloc;
1124*1c60b9acSAndroid Build Coastguard Worker 		else
1125*1c60b9acSAndroid Build Coastguard Worker 			ebuf.len = (int)wsi->a.context->pt_serv_buf_size;
1126*1c60b9acSAndroid Build Coastguard Worker 
1127*1c60b9acSAndroid Build Coastguard Worker 		if ((unsigned int)ebuf.len > wsi->a.context->pt_serv_buf_size)
1128*1c60b9acSAndroid Build Coastguard Worker 			ebuf.len = (int)wsi->a.context->pt_serv_buf_size;
1129*1c60b9acSAndroid Build Coastguard Worker 
1130*1c60b9acSAndroid Build Coastguard Worker 		if ((int)pending > ebuf.len)
1131*1c60b9acSAndroid Build Coastguard Worker 			pending = (unsigned int)ebuf.len;
1132*1c60b9acSAndroid Build Coastguard Worker 
1133*1c60b9acSAndroid Build Coastguard Worker 		ebuf.len = lws_ssl_capable_read(wsi, ebuf.token,
1134*1c60b9acSAndroid Build Coastguard Worker 						(size_t)(pending ? pending :
1135*1c60b9acSAndroid Build Coastguard Worker 						(unsigned int)ebuf.len));
1136*1c60b9acSAndroid Build Coastguard Worker 		switch (ebuf.len) {
1137*1c60b9acSAndroid Build Coastguard Worker 		case 0:
1138*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: zero length read\n",
1139*1c60b9acSAndroid Build Coastguard Worker 				  __func__);
1140*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_PLEASE_CLOSE_ME;
1141*1c60b9acSAndroid Build Coastguard Worker 		case LWS_SSL_CAPABLE_MORE_SERVICE:
1142*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("SSL Capable more service\n");
1143*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_HANDLED;
1144*1c60b9acSAndroid Build Coastguard Worker 		case LWS_SSL_CAPABLE_ERROR:
1145*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: LWS_SSL_CAPABLE_ERROR\n",
1146*1c60b9acSAndroid Build Coastguard Worker 					__func__);
1147*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_PLEASE_CLOSE_ME;
1148*1c60b9acSAndroid Build Coastguard Worker 		}
1149*1c60b9acSAndroid Build Coastguard Worker 
1150*1c60b9acSAndroid Build Coastguard Worker 		/*
1151*1c60b9acSAndroid Build Coastguard Worker 		 * coverity thinks ssl_capable_read() may read over
1152*1c60b9acSAndroid Build Coastguard Worker 		 * 2GB.  Dissuade it...
1153*1c60b9acSAndroid Build Coastguard Worker 		 */
1154*1c60b9acSAndroid Build Coastguard Worker 		ebuf.len &= 0x7fffffff;
1155*1c60b9acSAndroid Build Coastguard Worker 	}
1156*1c60b9acSAndroid Build Coastguard Worker 
1157*1c60b9acSAndroid Build Coastguard Worker drain:
1158*1c60b9acSAndroid Build Coastguard Worker 
1159*1c60b9acSAndroid Build Coastguard Worker 	/*
1160*1c60b9acSAndroid Build Coastguard Worker 	 * give any active extensions a chance to munge the buffer
1161*1c60b9acSAndroid Build Coastguard Worker 	 * before parse.  We pass in a pointer to an lws_tokens struct
1162*1c60b9acSAndroid Build Coastguard Worker 	 * prepared with the default buffer and content length that's in
1163*1c60b9acSAndroid Build Coastguard Worker 	 * there.  Rather than rewrite the default buffer, extensions
1164*1c60b9acSAndroid Build Coastguard Worker 	 * that expect to grow the buffer can adapt .token to
1165*1c60b9acSAndroid Build Coastguard Worker 	 * point to their own per-connection buffer in the extension
1166*1c60b9acSAndroid Build Coastguard Worker 	 * user allocation.  By default with no extensions or no
1167*1c60b9acSAndroid Build Coastguard Worker 	 * extension callback handling, just the normal input buffer is
1168*1c60b9acSAndroid Build Coastguard Worker 	 * used then so it is efficient.
1169*1c60b9acSAndroid Build Coastguard Worker 	 */
1170*1c60b9acSAndroid Build Coastguard Worker 	m = 0;
1171*1c60b9acSAndroid Build Coastguard Worker 	do {
1172*1c60b9acSAndroid Build Coastguard Worker 
1173*1c60b9acSAndroid Build Coastguard Worker 		/* service incoming data */
1174*1c60b9acSAndroid Build Coastguard Worker 		//lws_buflist_describe(&wsi->buflist, wsi, __func__);
1175*1c60b9acSAndroid Build Coastguard Worker 		if (ebuf.len > 0) {
1176*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H2)
1177*1c60b9acSAndroid Build Coastguard Worker 			if (lwsi_role_h2(wsi) && lwsi_state(wsi) != LRS_BODY &&
1178*1c60b9acSAndroid Build Coastguard Worker 			    lwsi_state(wsi) != LRS_DISCARD_BODY)
1179*1c60b9acSAndroid Build Coastguard Worker 				n = lws_read_h2(wsi, ebuf.token,
1180*1c60b9acSAndroid Build Coastguard Worker 					     (unsigned int)ebuf.len);
1181*1c60b9acSAndroid Build Coastguard Worker 			else
1182*1c60b9acSAndroid Build Coastguard Worker #endif
1183*1c60b9acSAndroid Build Coastguard Worker 				n = lws_read_h1(wsi, ebuf.token,
1184*1c60b9acSAndroid Build Coastguard Worker 					     (unsigned int)ebuf.len);
1185*1c60b9acSAndroid Build Coastguard Worker 
1186*1c60b9acSAndroid Build Coastguard Worker 			if (n < 0) {
1187*1c60b9acSAndroid Build Coastguard Worker 				/* we closed wsi */
1188*1c60b9acSAndroid Build Coastguard Worker 				return LWS_HPI_RET_WSI_ALREADY_DIED;
1189*1c60b9acSAndroid Build Coastguard Worker 			}
1190*1c60b9acSAndroid Build Coastguard Worker 			//lws_buflist_describe(&wsi->buflist, wsi, __func__);
1191*1c60b9acSAndroid Build Coastguard Worker 			//lwsl_notice("%s: consuming %d / %d\n", __func__, n, ebuf.len);
1192*1c60b9acSAndroid Build Coastguard Worker 			if (ebuf.len < 0 ||
1193*1c60b9acSAndroid Build Coastguard Worker 			    lws_buflist_aware_finished_consuming(wsi, &ebuf, n,
1194*1c60b9acSAndroid Build Coastguard Worker 							buffered, __func__))
1195*1c60b9acSAndroid Build Coastguard Worker 				return LWS_HPI_RET_PLEASE_CLOSE_ME;
1196*1c60b9acSAndroid Build Coastguard Worker 		}
1197*1c60b9acSAndroid Build Coastguard Worker 
1198*1c60b9acSAndroid Build Coastguard Worker 		ebuf.token = NULL;
1199*1c60b9acSAndroid Build Coastguard Worker 		ebuf.len = 0;
1200*1c60b9acSAndroid Build Coastguard Worker 	} while (m);
1201*1c60b9acSAndroid Build Coastguard Worker 
1202*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->http.ah
1203*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
1204*1c60b9acSAndroid Build Coastguard Worker 			&& !wsi->client_h2_alpn
1205*1c60b9acSAndroid Build Coastguard Worker #endif
1206*1c60b9acSAndroid Build Coastguard Worker 			) {
1207*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: %p: detaching ah\n", __func__, wsi);
1208*1c60b9acSAndroid Build Coastguard Worker 		lws_header_table_detach(wsi, 0);
1209*1c60b9acSAndroid Build Coastguard Worker 	}
1210*1c60b9acSAndroid Build Coastguard Worker 
1211*1c60b9acSAndroid Build Coastguard Worker 	pending = (unsigned int)lws_ssl_pending(wsi);
1212*1c60b9acSAndroid Build Coastguard Worker 
1213*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
1214*1c60b9acSAndroid Build Coastguard Worker 	if (!pending && (wsi->flags & LCCSCF_PRIORITIZE_READS) &&
1215*1c60b9acSAndroid Build Coastguard Worker 	    lws_buflist_total_len(&wsi->buflist))
1216*1c60b9acSAndroid Build Coastguard Worker 		pending = 9999999;
1217*1c60b9acSAndroid Build Coastguard Worker #endif
1218*1c60b9acSAndroid Build Coastguard Worker 
1219*1c60b9acSAndroid Build Coastguard Worker 	if (pending) {
1220*1c60b9acSAndroid Build Coastguard Worker 		if (lws_is_ws_with_ext(wsi))
1221*1c60b9acSAndroid Build Coastguard Worker 			pending = pending > wsi->ws->rx_ubuf_alloc ?
1222*1c60b9acSAndroid Build Coastguard Worker 				wsi->ws->rx_ubuf_alloc : pending;
1223*1c60b9acSAndroid Build Coastguard Worker 		else
1224*1c60b9acSAndroid Build Coastguard Worker 			pending = pending > wsi->a.context->pt_serv_buf_size ?
1225*1c60b9acSAndroid Build Coastguard Worker 				wsi->a.context->pt_serv_buf_size : pending;
1226*1c60b9acSAndroid Build Coastguard Worker 		if (--sanity)
1227*1c60b9acSAndroid Build Coastguard Worker 			goto read;
1228*1c60b9acSAndroid Build Coastguard Worker 		else
1229*1c60b9acSAndroid Build Coastguard Worker 			/*
1230*1c60b9acSAndroid Build Coastguard Worker 			 * Something has gone wrong, we are spinning...
1231*1c60b9acSAndroid Build Coastguard Worker 			 * let's bail on this connection
1232*1c60b9acSAndroid Build Coastguard Worker 			 */
1233*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HPI_RET_PLEASE_CLOSE_ME;
1234*1c60b9acSAndroid Build Coastguard Worker 	}
1235*1c60b9acSAndroid Build Coastguard Worker 
1236*1c60b9acSAndroid Build Coastguard Worker 	if (buffered && /* were draining, now nothing left */
1237*1c60b9acSAndroid Build Coastguard Worker 	    !lws_buflist_next_segment_len(&wsi->buflist, NULL)) {
1238*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: %p flow buf: drained\n", __func__, wsi);
1239*1c60b9acSAndroid Build Coastguard Worker 		/* having drained the rxflow buffer, can rearm POLLIN */
1240*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITH_SERVER)
1241*1c60b9acSAndroid Build Coastguard Worker 		n =
1242*1c60b9acSAndroid Build Coastguard Worker #endif
1243*1c60b9acSAndroid Build Coastguard Worker 		__lws_rx_flow_control(wsi);
1244*1c60b9acSAndroid Build Coastguard Worker 		/* n ignored, needed for NO_SERVER case */
1245*1c60b9acSAndroid Build Coastguard Worker 	}
1246*1c60b9acSAndroid Build Coastguard Worker 
1247*1c60b9acSAndroid Build Coastguard Worker 	/* n = 0 */
1248*1c60b9acSAndroid Build Coastguard Worker 	return LWS_HPI_RET_HANDLED;
1249*1c60b9acSAndroid Build Coastguard Worker }
1250*1c60b9acSAndroid Build Coastguard Worker 
1251*1c60b9acSAndroid Build Coastguard Worker 
rops_handle_POLLOUT_ws(struct lws * wsi)1252*1c60b9acSAndroid Build Coastguard Worker int rops_handle_POLLOUT_ws(struct lws *wsi)
1253*1c60b9acSAndroid Build Coastguard Worker {
1254*1c60b9acSAndroid Build Coastguard Worker 	int write_type = LWS_WRITE_PONG;
1255*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
1256*1c60b9acSAndroid Build Coastguard Worker 	struct lws_ext_pm_deflate_rx_ebufs pmdrx;
1257*1c60b9acSAndroid Build Coastguard Worker 	int ret, m;
1258*1c60b9acSAndroid Build Coastguard Worker #endif
1259*1c60b9acSAndroid Build Coastguard Worker 	int n;
1260*1c60b9acSAndroid Build Coastguard Worker 
1261*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
1262*1c60b9acSAndroid Build Coastguard Worker 	lwsl_debug("%s: %s: wsi->ws->tx_draining_ext %d\n", __func__,
1263*1c60b9acSAndroid Build Coastguard Worker 			wsi->a.protocol->name, wsi->ws->tx_draining_ext);
1264*1c60b9acSAndroid Build Coastguard Worker #endif
1265*1c60b9acSAndroid Build Coastguard Worker 
1266*1c60b9acSAndroid Build Coastguard Worker 	/* Priority 3: pending control packets (pong or close)
1267*1c60b9acSAndroid Build Coastguard Worker 	 *
1268*1c60b9acSAndroid Build Coastguard Worker 	 * 3a: close notification packet requested from close api
1269*1c60b9acSAndroid Build Coastguard Worker 	 */
1270*1c60b9acSAndroid Build Coastguard Worker 
1271*1c60b9acSAndroid Build Coastguard Worker 	if (lwsi_state(wsi) == LRS_WAITING_TO_SEND_CLOSE) {
1272*1c60b9acSAndroid Build Coastguard Worker 		lwsl_debug("sending close packet\n");
1273*1c60b9acSAndroid Build Coastguard Worker 		lwsl_hexdump_debug(&wsi->ws->ping_payload_buf[LWS_PRE],
1274*1c60b9acSAndroid Build Coastguard Worker 				   wsi->ws->close_in_ping_buffer_len);
1275*1c60b9acSAndroid Build Coastguard Worker 		wsi->waiting_to_send_close_frame = 0;
1276*1c60b9acSAndroid Build Coastguard Worker 		n = lws_write(wsi, &wsi->ws->ping_payload_buf[LWS_PRE],
1277*1c60b9acSAndroid Build Coastguard Worker 			      wsi->ws->close_in_ping_buffer_len,
1278*1c60b9acSAndroid Build Coastguard Worker 			      LWS_WRITE_CLOSE);
1279*1c60b9acSAndroid Build Coastguard Worker 		if (n >= 0) {
1280*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->close_needs_ack) {
1281*1c60b9acSAndroid Build Coastguard Worker 				lwsi_set_state(wsi, LRS_AWAITING_CLOSE_ACK);
1282*1c60b9acSAndroid Build Coastguard Worker 				lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_ACK,
1283*1c60b9acSAndroid Build Coastguard Worker 						5);
1284*1c60b9acSAndroid Build Coastguard Worker 				lwsl_debug("sent close, await ack\n");
1285*1c60b9acSAndroid Build Coastguard Worker 
1286*1c60b9acSAndroid Build Coastguard Worker 				return LWS_HP_RET_BAIL_OK;
1287*1c60b9acSAndroid Build Coastguard Worker 			}
1288*1c60b9acSAndroid Build Coastguard Worker 			wsi->close_needs_ack = 0;
1289*1c60b9acSAndroid Build Coastguard Worker 			lwsi_set_state(wsi, LRS_RETURNED_CLOSE);
1290*1c60b9acSAndroid Build Coastguard Worker 		}
1291*1c60b9acSAndroid Build Coastguard Worker 
1292*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HP_RET_BAIL_DIE;
1293*1c60b9acSAndroid Build Coastguard Worker 	}
1294*1c60b9acSAndroid Build Coastguard Worker 
1295*1c60b9acSAndroid Build Coastguard Worker 	/* else, the send failed and we should just hang up */
1296*1c60b9acSAndroid Build Coastguard Worker 
1297*1c60b9acSAndroid Build Coastguard Worker 	if ((lwsi_role_ws(wsi) && wsi->ws->pong_pending_flag) ||
1298*1c60b9acSAndroid Build Coastguard Worker 	    (lwsi_state(wsi) == LRS_RETURNED_CLOSE &&
1299*1c60b9acSAndroid Build Coastguard Worker 	     wsi->ws->payload_is_close)) {
1300*1c60b9acSAndroid Build Coastguard Worker 
1301*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->ws->payload_is_close)
1302*1c60b9acSAndroid Build Coastguard Worker 			write_type = LWS_WRITE_CLOSE;
1303*1c60b9acSAndroid Build Coastguard Worker 		else {
1304*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->wsistate_pre_close) {
1305*1c60b9acSAndroid Build Coastguard Worker 				/* we started close flow, forget pong */
1306*1c60b9acSAndroid Build Coastguard Worker 				wsi->ws->pong_pending_flag = 0;
1307*1c60b9acSAndroid Build Coastguard Worker 				return LWS_HP_RET_BAIL_OK;
1308*1c60b9acSAndroid Build Coastguard Worker 			}
1309*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("issuing pong %d on %s\n",
1310*1c60b9acSAndroid Build Coastguard Worker 				  wsi->ws->pong_payload_len, lws_wsi_tag(wsi));
1311*1c60b9acSAndroid Build Coastguard Worker 		}
1312*1c60b9acSAndroid Build Coastguard Worker 
1313*1c60b9acSAndroid Build Coastguard Worker 		n = lws_write(wsi, &wsi->ws->pong_payload_buf[LWS_PRE],
1314*1c60b9acSAndroid Build Coastguard Worker 			      wsi->ws->pong_payload_len, (enum lws_write_protocol)write_type);
1315*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0)
1316*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HP_RET_BAIL_DIE;
1317*1c60b9acSAndroid Build Coastguard Worker 
1318*1c60b9acSAndroid Build Coastguard Worker 		/* well he is sent, mark him done */
1319*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->pong_pending_flag = 0;
1320*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->ws->payload_is_close) {
1321*1c60b9acSAndroid Build Coastguard Worker 			// assert(0);
1322*1c60b9acSAndroid Build Coastguard Worker 			/* oh... a close frame was it... then we are done */
1323*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HP_RET_BAIL_DIE;
1324*1c60b9acSAndroid Build Coastguard Worker 		}
1325*1c60b9acSAndroid Build Coastguard Worker 
1326*1c60b9acSAndroid Build Coastguard Worker 		/* otherwise for PING, leave POLLOUT active either way */
1327*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HP_RET_BAIL_OK;
1328*1c60b9acSAndroid Build Coastguard Worker 	}
1329*1c60b9acSAndroid Build Coastguard Worker 
1330*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->socket_is_permanently_unusable &&
1331*1c60b9acSAndroid Build Coastguard Worker 	    wsi->ws->send_check_ping) {
1332*1c60b9acSAndroid Build Coastguard Worker 
1333*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: issuing ping on wsi %s: %s %s h2: %d\n", __func__,
1334*1c60b9acSAndroid Build Coastguard Worker 				lws_wsi_tag(wsi),
1335*1c60b9acSAndroid Build Coastguard Worker 				wsi->role_ops->name, wsi->a.protocol->name,
1336*1c60b9acSAndroid Build Coastguard Worker 				wsi->mux_substream);
1337*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->send_check_ping = 0;
1338*1c60b9acSAndroid Build Coastguard Worker 		n = lws_write(wsi, &wsi->ws->ping_payload_buf[LWS_PRE],
1339*1c60b9acSAndroid Build Coastguard Worker 			      0, LWS_WRITE_PING);
1340*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0)
1341*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HP_RET_BAIL_DIE;
1342*1c60b9acSAndroid Build Coastguard Worker 
1343*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HP_RET_BAIL_OK;
1344*1c60b9acSAndroid Build Coastguard Worker 	}
1345*1c60b9acSAndroid Build Coastguard Worker 
1346*1c60b9acSAndroid Build Coastguard Worker 	/* Priority 4: if we are closing, not allowed to send more data frags
1347*1c60b9acSAndroid Build Coastguard Worker 	 *	       which means user callback or tx ext flush banned now
1348*1c60b9acSAndroid Build Coastguard Worker 	 */
1349*1c60b9acSAndroid Build Coastguard Worker 	if (lwsi_state(wsi) == LRS_RETURNED_CLOSE)
1350*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HP_RET_USER_SERVICE;
1351*1c60b9acSAndroid Build Coastguard Worker 
1352*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
1353*1c60b9acSAndroid Build Coastguard Worker 	/* Priority 5: Tx path extension with more to send
1354*1c60b9acSAndroid Build Coastguard Worker 	 *
1355*1c60b9acSAndroid Build Coastguard Worker 	 *	       These are handled as new fragments each time around
1356*1c60b9acSAndroid Build Coastguard Worker 	 *	       So while we must block new writeable callback to enforce
1357*1c60b9acSAndroid Build Coastguard Worker 	 *	       payload ordering, but since they are always complete
1358*1c60b9acSAndroid Build Coastguard Worker 	 *	       fragments control packets can interleave OK.
1359*1c60b9acSAndroid Build Coastguard Worker 	 */
1360*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->ws->tx_draining_ext) {
1361*1c60b9acSAndroid Build Coastguard Worker 		lwsl_ext("SERVICING TX EXT DRAINING\n");
1362*1c60b9acSAndroid Build Coastguard Worker 		if (lws_write(wsi, NULL, 0, LWS_WRITE_CONTINUATION) < 0)
1363*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HP_RET_BAIL_DIE;
1364*1c60b9acSAndroid Build Coastguard Worker 		/* leave POLLOUT active */
1365*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HP_RET_BAIL_OK;
1366*1c60b9acSAndroid Build Coastguard Worker 	}
1367*1c60b9acSAndroid Build Coastguard Worker 
1368*1c60b9acSAndroid Build Coastguard Worker 	/* Priority 6: extensions
1369*1c60b9acSAndroid Build Coastguard Worker 	 */
1370*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->ws->extension_data_pending && !wsi->ws->tx_draining_ext) {
1371*1c60b9acSAndroid Build Coastguard Worker 		lwsl_ext("%s: !wsi->ws->extension_data_pending\n", __func__);
1372*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HP_RET_USER_SERVICE;
1373*1c60b9acSAndroid Build Coastguard Worker 	}
1374*1c60b9acSAndroid Build Coastguard Worker 
1375*1c60b9acSAndroid Build Coastguard Worker 	/*
1376*1c60b9acSAndroid Build Coastguard Worker 	 * Check in on the active extensions, see if they had pending stuff to
1377*1c60b9acSAndroid Build Coastguard Worker 	 * spill... they need to get the first look-in otherwise sequence will
1378*1c60b9acSAndroid Build Coastguard Worker 	 * be disordered.
1379*1c60b9acSAndroid Build Coastguard Worker 	 *
1380*1c60b9acSAndroid Build Coastguard Worker 	 * coming here with a NULL, zero-length ebuf means just spill pending
1381*1c60b9acSAndroid Build Coastguard Worker 	 */
1382*1c60b9acSAndroid Build Coastguard Worker 
1383*1c60b9acSAndroid Build Coastguard Worker 	ret = 1;
1384*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->role_ops == &role_ops_raw_skt
1385*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_RAW_FILE)
1386*1c60b9acSAndroid Build Coastguard Worker 		|| wsi->role_ops == &role_ops_raw_file
1387*1c60b9acSAndroid Build Coastguard Worker #endif
1388*1c60b9acSAndroid Build Coastguard Worker 	    )
1389*1c60b9acSAndroid Build Coastguard Worker 		ret = 0;
1390*1c60b9acSAndroid Build Coastguard Worker 
1391*1c60b9acSAndroid Build Coastguard Worker 	while (ret == 1) {
1392*1c60b9acSAndroid Build Coastguard Worker 
1393*1c60b9acSAndroid Build Coastguard Worker 		/* default to nobody has more to spill */
1394*1c60b9acSAndroid Build Coastguard Worker 
1395*1c60b9acSAndroid Build Coastguard Worker 		ret = 0;
1396*1c60b9acSAndroid Build Coastguard Worker 		pmdrx.eb_in.token = NULL;
1397*1c60b9acSAndroid Build Coastguard Worker 		pmdrx.eb_in.len = 0;
1398*1c60b9acSAndroid Build Coastguard Worker 
1399*1c60b9acSAndroid Build Coastguard Worker 		/* give every extension a chance to spill */
1400*1c60b9acSAndroid Build Coastguard Worker 
1401*1c60b9acSAndroid Build Coastguard Worker 		m = lws_ext_cb_active(wsi, LWS_EXT_CB_PACKET_TX_PRESEND,
1402*1c60b9acSAndroid Build Coastguard Worker 				      &pmdrx, 0);
1403*1c60b9acSAndroid Build Coastguard Worker 		if (m < 0) {
1404*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("ext reports fatal error\n");
1405*1c60b9acSAndroid Build Coastguard Worker 			return LWS_HP_RET_BAIL_DIE;
1406*1c60b9acSAndroid Build Coastguard Worker 		}
1407*1c60b9acSAndroid Build Coastguard Worker 		if (m)
1408*1c60b9acSAndroid Build Coastguard Worker 			/*
1409*1c60b9acSAndroid Build Coastguard Worker 			 * at least one extension told us he has more
1410*1c60b9acSAndroid Build Coastguard Worker 			 * to spill, so we will go around again after
1411*1c60b9acSAndroid Build Coastguard Worker 			 */
1412*1c60b9acSAndroid Build Coastguard Worker 			ret = 1;
1413*1c60b9acSAndroid Build Coastguard Worker 
1414*1c60b9acSAndroid Build Coastguard Worker 		/* assuming they gave us something to send, send it */
1415*1c60b9acSAndroid Build Coastguard Worker 
1416*1c60b9acSAndroid Build Coastguard Worker 		if (pmdrx.eb_in.len) {
1417*1c60b9acSAndroid Build Coastguard Worker 			n = lws_issue_raw(wsi, (unsigned char *)pmdrx.eb_in.token,
1418*1c60b9acSAndroid Build Coastguard Worker 					(unsigned int)pmdrx.eb_in.len);
1419*1c60b9acSAndroid Build Coastguard Worker 			if (n < 0) {
1420*1c60b9acSAndroid Build Coastguard Worker 				lwsl_info("closing from POLLOUT spill\n");
1421*1c60b9acSAndroid Build Coastguard Worker 				return LWS_HP_RET_BAIL_DIE;
1422*1c60b9acSAndroid Build Coastguard Worker 			}
1423*1c60b9acSAndroid Build Coastguard Worker 			/*
1424*1c60b9acSAndroid Build Coastguard Worker 			 * Keep amount spilled small to minimize chance of this
1425*1c60b9acSAndroid Build Coastguard Worker 			 */
1426*1c60b9acSAndroid Build Coastguard Worker 			if (n != pmdrx.eb_in.len) {
1427*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("Unable to spill ext %d vs %d\n",
1428*1c60b9acSAndroid Build Coastguard Worker 						pmdrx.eb_in.len, n);
1429*1c60b9acSAndroid Build Coastguard Worker 				return LWS_HP_RET_BAIL_DIE;
1430*1c60b9acSAndroid Build Coastguard Worker 			}
1431*1c60b9acSAndroid Build Coastguard Worker 		} else
1432*1c60b9acSAndroid Build Coastguard Worker 			continue;
1433*1c60b9acSAndroid Build Coastguard Worker 
1434*1c60b9acSAndroid Build Coastguard Worker 		/* no extension has more to spill */
1435*1c60b9acSAndroid Build Coastguard Worker 
1436*1c60b9acSAndroid Build Coastguard Worker 		if (!ret)
1437*1c60b9acSAndroid Build Coastguard Worker 			continue;
1438*1c60b9acSAndroid Build Coastguard Worker 
1439*1c60b9acSAndroid Build Coastguard Worker 		/*
1440*1c60b9acSAndroid Build Coastguard Worker 		 * There's more to spill from an extension, but we just sent
1441*1c60b9acSAndroid Build Coastguard Worker 		 * something... did that leave the pipe choked?
1442*1c60b9acSAndroid Build Coastguard Worker 		 */
1443*1c60b9acSAndroid Build Coastguard Worker 
1444*1c60b9acSAndroid Build Coastguard Worker 		if (!lws_send_pipe_choked(wsi))
1445*1c60b9acSAndroid Build Coastguard Worker 			/* no we could add more */
1446*1c60b9acSAndroid Build Coastguard Worker 			continue;
1447*1c60b9acSAndroid Build Coastguard Worker 
1448*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("choked in POLLOUT service\n");
1449*1c60b9acSAndroid Build Coastguard Worker 
1450*1c60b9acSAndroid Build Coastguard Worker 		/*
1451*1c60b9acSAndroid Build Coastguard Worker 		 * Yes, he's choked.  Leave the POLLOUT masked on so we will
1452*1c60b9acSAndroid Build Coastguard Worker 		 * come back here when he is unchoked.  Don't call the user
1453*1c60b9acSAndroid Build Coastguard Worker 		 * callback to enforce ordering of spilling, he'll get called
1454*1c60b9acSAndroid Build Coastguard Worker 		 * when we come back here and there's nothing more to spill.
1455*1c60b9acSAndroid Build Coastguard Worker 		 */
1456*1c60b9acSAndroid Build Coastguard Worker 
1457*1c60b9acSAndroid Build Coastguard Worker 		return LWS_HP_RET_BAIL_OK;
1458*1c60b9acSAndroid Build Coastguard Worker 	}
1459*1c60b9acSAndroid Build Coastguard Worker 
1460*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->extension_data_pending = 0;
1461*1c60b9acSAndroid Build Coastguard Worker #endif
1462*1c60b9acSAndroid Build Coastguard Worker 
1463*1c60b9acSAndroid Build Coastguard Worker 	return LWS_HP_RET_USER_SERVICE;
1464*1c60b9acSAndroid Build Coastguard Worker }
1465*1c60b9acSAndroid Build Coastguard Worker 
1466*1c60b9acSAndroid Build Coastguard Worker static int
rops_service_flag_pending_ws(struct lws_context * context,int tsi)1467*1c60b9acSAndroid Build Coastguard Worker rops_service_flag_pending_ws(struct lws_context *context, int tsi)
1468*1c60b9acSAndroid Build Coastguard Worker {
1469*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
1470*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &context->pt[tsi];
1471*1c60b9acSAndroid Build Coastguard Worker 	struct lws *wsi;
1472*1c60b9acSAndroid Build Coastguard Worker 	int forced = 0;
1473*1c60b9acSAndroid Build Coastguard Worker 
1474*1c60b9acSAndroid Build Coastguard Worker 	/* POLLIN faking (the pt lock is taken by the parent) */
1475*1c60b9acSAndroid Build Coastguard Worker 
1476*1c60b9acSAndroid Build Coastguard Worker 	/*
1477*1c60b9acSAndroid Build Coastguard Worker 	 * 1) For all guys with already-available ext data to drain, if they are
1478*1c60b9acSAndroid Build Coastguard Worker 	 * not flowcontrolled, fake their POLLIN status
1479*1c60b9acSAndroid Build Coastguard Worker 	 */
1480*1c60b9acSAndroid Build Coastguard Worker 	wsi = pt->ws.rx_draining_ext_list;
1481*1c60b9acSAndroid Build Coastguard Worker 	while (wsi && wsi->position_in_fds_table != LWS_NO_FDS_POS) {
1482*1c60b9acSAndroid Build Coastguard Worker 		pt->fds[wsi->position_in_fds_table].revents =
1483*1c60b9acSAndroid Build Coastguard Worker 			(short)((short)pt->fds[wsi->position_in_fds_table].revents |
1484*1c60b9acSAndroid Build Coastguard Worker 			(short)(pt->fds[wsi->position_in_fds_table].events & LWS_POLLIN));
1485*1c60b9acSAndroid Build Coastguard Worker 		if (pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN)
1486*1c60b9acSAndroid Build Coastguard Worker 			forced = 1;
1487*1c60b9acSAndroid Build Coastguard Worker 
1488*1c60b9acSAndroid Build Coastguard Worker 		wsi = wsi->ws->rx_draining_ext_list;
1489*1c60b9acSAndroid Build Coastguard Worker 	}
1490*1c60b9acSAndroid Build Coastguard Worker 
1491*1c60b9acSAndroid Build Coastguard Worker 	return forced;
1492*1c60b9acSAndroid Build Coastguard Worker #else
1493*1c60b9acSAndroid Build Coastguard Worker 	return 0;
1494*1c60b9acSAndroid Build Coastguard Worker #endif
1495*1c60b9acSAndroid Build Coastguard Worker }
1496*1c60b9acSAndroid Build Coastguard Worker 
1497*1c60b9acSAndroid Build Coastguard Worker static int
rops_close_via_role_protocol_ws(struct lws * wsi,enum lws_close_status reason)1498*1c60b9acSAndroid Build Coastguard Worker rops_close_via_role_protocol_ws(struct lws *wsi, enum lws_close_status reason)
1499*1c60b9acSAndroid Build Coastguard Worker {
1500*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->ws)
1501*1c60b9acSAndroid Build Coastguard Worker 		return 0;
1502*1c60b9acSAndroid Build Coastguard Worker 
1503*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->ws->close_in_ping_buffer_len && /* already a reason */
1504*1c60b9acSAndroid Build Coastguard Worker 	     (reason == LWS_CLOSE_STATUS_NOSTATUS ||
1505*1c60b9acSAndroid Build Coastguard Worker 	      reason == LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY))
1506*1c60b9acSAndroid Build Coastguard Worker 		return 0;
1507*1c60b9acSAndroid Build Coastguard Worker 
1508*1c60b9acSAndroid Build Coastguard Worker 	lwsl_debug("%s: sending close indication...\n", __func__);
1509*1c60b9acSAndroid Build Coastguard Worker 
1510*1c60b9acSAndroid Build Coastguard Worker 	/* if no prepared close reason, use 1000 and no aux data */
1511*1c60b9acSAndroid Build Coastguard Worker 
1512*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->ws->close_in_ping_buffer_len) {
1513*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->close_in_ping_buffer_len = 2;
1514*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->ping_payload_buf[LWS_PRE] = (reason >> 8) & 0xff;
1515*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->ping_payload_buf[LWS_PRE + 1] = reason & 0xff;
1516*1c60b9acSAndroid Build Coastguard Worker 	}
1517*1c60b9acSAndroid Build Coastguard Worker 
1518*1c60b9acSAndroid Build Coastguard Worker 	wsi->waiting_to_send_close_frame = 1;
1519*1c60b9acSAndroid Build Coastguard Worker 	wsi->close_needs_ack = 1;
1520*1c60b9acSAndroid Build Coastguard Worker 	lwsi_set_state(wsi, LRS_WAITING_TO_SEND_CLOSE);
1521*1c60b9acSAndroid Build Coastguard Worker 	__lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_SEND, 5);
1522*1c60b9acSAndroid Build Coastguard Worker 
1523*1c60b9acSAndroid Build Coastguard Worker 	lws_callback_on_writable(wsi);
1524*1c60b9acSAndroid Build Coastguard Worker 
1525*1c60b9acSAndroid Build Coastguard Worker 	return 1;
1526*1c60b9acSAndroid Build Coastguard Worker }
1527*1c60b9acSAndroid Build Coastguard Worker 
1528*1c60b9acSAndroid Build Coastguard Worker static int
rops_close_role_ws(struct lws_context_per_thread * pt,struct lws * wsi)1529*1c60b9acSAndroid Build Coastguard Worker rops_close_role_ws(struct lws_context_per_thread *pt, struct lws *wsi)
1530*1c60b9acSAndroid Build Coastguard Worker {
1531*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->ws)
1532*1c60b9acSAndroid Build Coastguard Worker 		return 0;
1533*1c60b9acSAndroid Build Coastguard Worker 
1534*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
1535*1c60b9acSAndroid Build Coastguard Worker 
1536*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->ws->rx_draining_ext) {
1537*1c60b9acSAndroid Build Coastguard Worker 		struct lws **w = &pt->ws.rx_draining_ext_list;
1538*1c60b9acSAndroid Build Coastguard Worker 
1539*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->rx_draining_ext = 0;
1540*1c60b9acSAndroid Build Coastguard Worker 		/* remove us from context draining ext list */
1541*1c60b9acSAndroid Build Coastguard Worker 		while (*w) {
1542*1c60b9acSAndroid Build Coastguard Worker 			if (*w == wsi) {
1543*1c60b9acSAndroid Build Coastguard Worker 				*w = wsi->ws->rx_draining_ext_list;
1544*1c60b9acSAndroid Build Coastguard Worker 				break;
1545*1c60b9acSAndroid Build Coastguard Worker 			}
1546*1c60b9acSAndroid Build Coastguard Worker 			w = &((*w)->ws->rx_draining_ext_list);
1547*1c60b9acSAndroid Build Coastguard Worker 		}
1548*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->rx_draining_ext_list = NULL;
1549*1c60b9acSAndroid Build Coastguard Worker 	}
1550*1c60b9acSAndroid Build Coastguard Worker 
1551*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->ws->tx_draining_ext) {
1552*1c60b9acSAndroid Build Coastguard Worker 		struct lws **w = &pt->ws.tx_draining_ext_list;
1553*1c60b9acSAndroid Build Coastguard Worker 		lwsl_ext("%s: CLEARING tx_draining_ext\n", __func__);
1554*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->tx_draining_ext = 0;
1555*1c60b9acSAndroid Build Coastguard Worker 		/* remove us from context draining ext list */
1556*1c60b9acSAndroid Build Coastguard Worker 		while (*w) {
1557*1c60b9acSAndroid Build Coastguard Worker 			if (*w == wsi) {
1558*1c60b9acSAndroid Build Coastguard Worker 				*w = wsi->ws->tx_draining_ext_list;
1559*1c60b9acSAndroid Build Coastguard Worker 				break;
1560*1c60b9acSAndroid Build Coastguard Worker 			}
1561*1c60b9acSAndroid Build Coastguard Worker 			w = &((*w)->ws->tx_draining_ext_list);
1562*1c60b9acSAndroid Build Coastguard Worker 		}
1563*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->tx_draining_ext_list = NULL;
1564*1c60b9acSAndroid Build Coastguard Worker 	}
1565*1c60b9acSAndroid Build Coastguard Worker #endif
1566*1c60b9acSAndroid Build Coastguard Worker 	lws_free_set_NULL(wsi->ws->rx_ubuf);
1567*1c60b9acSAndroid Build Coastguard Worker 
1568*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->pong_payload_len = 0;
1569*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->pong_pending_flag = 0;
1570*1c60b9acSAndroid Build Coastguard Worker 
1571*1c60b9acSAndroid Build Coastguard Worker 	/* deallocate any active extension contexts */
1572*1c60b9acSAndroid Build Coastguard Worker 
1573*1c60b9acSAndroid Build Coastguard Worker 	if (lws_ext_cb_active(wsi, LWS_EXT_CB_DESTROY, NULL, 0) < 0)
1574*1c60b9acSAndroid Build Coastguard Worker 		lwsl_warn("extension destruction failed\n");
1575*1c60b9acSAndroid Build Coastguard Worker 
1576*1c60b9acSAndroid Build Coastguard Worker 	return 0;
1577*1c60b9acSAndroid Build Coastguard Worker }
1578*1c60b9acSAndroid Build Coastguard Worker 
1579*1c60b9acSAndroid Build Coastguard Worker static int
rops_write_role_protocol_ws(struct lws * wsi,unsigned char * buf,size_t len,enum lws_write_protocol * wp)1580*1c60b9acSAndroid Build Coastguard Worker rops_write_role_protocol_ws(struct lws *wsi, unsigned char *buf, size_t len,
1581*1c60b9acSAndroid Build Coastguard Worker 			    enum lws_write_protocol *wp)
1582*1c60b9acSAndroid Build Coastguard Worker {
1583*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
1584*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
1585*1c60b9acSAndroid Build Coastguard Worker 	enum lws_write_protocol wpt;
1586*1c60b9acSAndroid Build Coastguard Worker #endif
1587*1c60b9acSAndroid Build Coastguard Worker 	struct lws_ext_pm_deflate_rx_ebufs pmdrx;
1588*1c60b9acSAndroid Build Coastguard Worker 	int masked7 = lwsi_role_client(wsi);
1589*1c60b9acSAndroid Build Coastguard Worker 	unsigned char is_masked_bit = 0;
1590*1c60b9acSAndroid Build Coastguard Worker 	unsigned char *dropmask = NULL;
1591*1c60b9acSAndroid Build Coastguard Worker 	size_t orig_len = len;
1592*1c60b9acSAndroid Build Coastguard Worker 	int pre = 0, n = 0;
1593*1c60b9acSAndroid Build Coastguard Worker 
1594*1c60b9acSAndroid Build Coastguard Worker 	// lwsl_err("%s: wp 0x%x len %d\n", __func__, *wp, (int)len);
1595*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
1596*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->ws->tx_draining_ext) {
1597*1c60b9acSAndroid Build Coastguard Worker 		/* remove us from the list */
1598*1c60b9acSAndroid Build Coastguard Worker 		struct lws **w = &pt->ws.tx_draining_ext_list;
1599*1c60b9acSAndroid Build Coastguard Worker 
1600*1c60b9acSAndroid Build Coastguard Worker 		lwsl_ext("%s: CLEARING tx_draining_ext\n", __func__);
1601*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->tx_draining_ext = 0;
1602*1c60b9acSAndroid Build Coastguard Worker 		/* remove us from context draining ext list */
1603*1c60b9acSAndroid Build Coastguard Worker 		while (*w) {
1604*1c60b9acSAndroid Build Coastguard Worker 			if (*w == wsi) {
1605*1c60b9acSAndroid Build Coastguard Worker 				*w = wsi->ws->tx_draining_ext_list;
1606*1c60b9acSAndroid Build Coastguard Worker 				break;
1607*1c60b9acSAndroid Build Coastguard Worker 			}
1608*1c60b9acSAndroid Build Coastguard Worker 			w = &((*w)->ws->tx_draining_ext_list);
1609*1c60b9acSAndroid Build Coastguard Worker 		}
1610*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->tx_draining_ext_list = NULL;
1611*1c60b9acSAndroid Build Coastguard Worker 
1612*1c60b9acSAndroid Build Coastguard Worker 		wpt = *wp;
1613*1c60b9acSAndroid Build Coastguard Worker 		*wp = (wsi->ws->tx_draining_stashed_wp & 0xc0) |
1614*1c60b9acSAndroid Build Coastguard Worker 				LWS_WRITE_CONTINUATION;
1615*1c60b9acSAndroid Build Coastguard Worker 
1616*1c60b9acSAndroid Build Coastguard Worker 		/*
1617*1c60b9acSAndroid Build Coastguard Worker 		 * When we are just flushing (len == 0), we can trust the
1618*1c60b9acSAndroid Build Coastguard Worker 		 * stashed wp info completely.  Otherwise adjust it to the
1619*1c60b9acSAndroid Build Coastguard Worker 		 * FIN status of the incoming packet.
1620*1c60b9acSAndroid Build Coastguard Worker 		 */
1621*1c60b9acSAndroid Build Coastguard Worker 
1622*1c60b9acSAndroid Build Coastguard Worker 		if (!(wpt & LWS_WRITE_NO_FIN) && len)
1623*1c60b9acSAndroid Build Coastguard Worker 			*wp &= (enum lws_write_protocol)~LWS_WRITE_NO_FIN;
1624*1c60b9acSAndroid Build Coastguard Worker 
1625*1c60b9acSAndroid Build Coastguard Worker 		lwsl_ext("FORCED draining wp to 0x%02X "
1626*1c60b9acSAndroid Build Coastguard Worker 			 "(stashed 0x%02X, incoming 0x%02X)\n", *wp,
1627*1c60b9acSAndroid Build Coastguard Worker 			 wsi->ws->tx_draining_stashed_wp, wpt);
1628*1c60b9acSAndroid Build Coastguard Worker 		// assert(0);
1629*1c60b9acSAndroid Build Coastguard Worker 	}
1630*1c60b9acSAndroid Build Coastguard Worker #endif
1631*1c60b9acSAndroid Build Coastguard Worker 
1632*1c60b9acSAndroid Build Coastguard Worker 	if (((*wp) & 0x1f) == LWS_WRITE_HTTP ||
1633*1c60b9acSAndroid Build Coastguard Worker 	    ((*wp) & 0x1f) == LWS_WRITE_HTTP_FINAL ||
1634*1c60b9acSAndroid Build Coastguard Worker 	    ((*wp) & 0x1f) == LWS_WRITE_HTTP_HEADERS_CONTINUATION ||
1635*1c60b9acSAndroid Build Coastguard Worker 	    ((*wp) & 0x1f) == LWS_WRITE_HTTP_HEADERS)
1636*1c60b9acSAndroid Build Coastguard Worker 		goto send_raw;
1637*1c60b9acSAndroid Build Coastguard Worker 
1638*1c60b9acSAndroid Build Coastguard Worker 
1639*1c60b9acSAndroid Build Coastguard Worker 
1640*1c60b9acSAndroid Build Coastguard Worker 	/* if we are continuing a frame that already had its header done */
1641*1c60b9acSAndroid Build Coastguard Worker 
1642*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->ws->inside_frame) {
1643*1c60b9acSAndroid Build Coastguard Worker 		lwsl_debug("INSIDE FRAME\n");
1644*1c60b9acSAndroid Build Coastguard Worker 		goto do_more_inside_frame;
1645*1c60b9acSAndroid Build Coastguard Worker 	}
1646*1c60b9acSAndroid Build Coastguard Worker 
1647*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->clean_buffer = 1;
1648*1c60b9acSAndroid Build Coastguard Worker 
1649*1c60b9acSAndroid Build Coastguard Worker 	/*
1650*1c60b9acSAndroid Build Coastguard Worker 	 * give a chance to the extensions to modify payload
1651*1c60b9acSAndroid Build Coastguard Worker 	 * the extension may decide to produce unlimited payload erratically
1652*1c60b9acSAndroid Build Coastguard Worker 	 * (eg, compression extension), so we require only that if he produces
1653*1c60b9acSAndroid Build Coastguard Worker 	 * something, it will be a complete fragment of the length known at
1654*1c60b9acSAndroid Build Coastguard Worker 	 * the time (just the fragment length known), and if he has
1655*1c60b9acSAndroid Build Coastguard Worker 	 * more we will come back next time he is writeable and allow him to
1656*1c60b9acSAndroid Build Coastguard Worker 	 * produce more fragments until he's drained.
1657*1c60b9acSAndroid Build Coastguard Worker 	 *
1658*1c60b9acSAndroid Build Coastguard Worker 	 * This allows what is sent each time it is writeable to be limited to
1659*1c60b9acSAndroid Build Coastguard Worker 	 * a size that can be sent without partial sends or blocking, allows
1660*1c60b9acSAndroid Build Coastguard Worker 	 * interleaving of control frames and other connection service.
1661*1c60b9acSAndroid Build Coastguard Worker 	 */
1662*1c60b9acSAndroid Build Coastguard Worker 
1663*1c60b9acSAndroid Build Coastguard Worker 	pmdrx.eb_in.token = buf;
1664*1c60b9acSAndroid Build Coastguard Worker 	pmdrx.eb_in.len = (int)len;
1665*1c60b9acSAndroid Build Coastguard Worker 
1666*1c60b9acSAndroid Build Coastguard Worker 	/* for the non-pm-deflate case */
1667*1c60b9acSAndroid Build Coastguard Worker 
1668*1c60b9acSAndroid Build Coastguard Worker 	pmdrx.eb_out = pmdrx.eb_in;
1669*1c60b9acSAndroid Build Coastguard Worker 
1670*1c60b9acSAndroid Build Coastguard Worker 	switch ((int)*wp) {
1671*1c60b9acSAndroid Build Coastguard Worker 	case LWS_WRITE_PING:
1672*1c60b9acSAndroid Build Coastguard Worker 	case LWS_WRITE_PONG:
1673*1c60b9acSAndroid Build Coastguard Worker 	case LWS_WRITE_CLOSE:
1674*1c60b9acSAndroid Build Coastguard Worker 		break;
1675*1c60b9acSAndroid Build Coastguard Worker 	default:
1676*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
1677*1c60b9acSAndroid Build Coastguard Worker 		n = lws_ext_cb_active(wsi, (int)LWS_EXT_CB_PAYLOAD_TX, &pmdrx, (int)*wp);
1678*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0)
1679*1c60b9acSAndroid Build Coastguard Worker 			return -1;
1680*1c60b9acSAndroid Build Coastguard Worker 		lwsl_ext("%s: defl ext ret %d, ext in remaining %d, "
1681*1c60b9acSAndroid Build Coastguard Worker 			    "out %d compressed (wp 0x%x)\n", __func__, n,
1682*1c60b9acSAndroid Build Coastguard Worker 			    (int)pmdrx.eb_in.len, (int)pmdrx.eb_out.len, *wp);
1683*1c60b9acSAndroid Build Coastguard Worker 
1684*1c60b9acSAndroid Build Coastguard Worker 		if (n == PMDR_HAS_PENDING) {
1685*1c60b9acSAndroid Build Coastguard Worker 			lwsl_ext("%s: HAS PENDING: write drain len %d "
1686*1c60b9acSAndroid Build Coastguard Worker 				    "(wp 0x%x) SETTING tx_draining_ext "
1687*1c60b9acSAndroid Build Coastguard Worker 				    "(remaining in %d)\n", __func__,
1688*1c60b9acSAndroid Build Coastguard Worker 				    (int)pmdrx.eb_out.len, *wp,
1689*1c60b9acSAndroid Build Coastguard Worker 				    (int)pmdrx.eb_in.len);
1690*1c60b9acSAndroid Build Coastguard Worker 			/* extension requires further draining */
1691*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->tx_draining_ext = 1;
1692*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->tx_draining_ext_list =
1693*1c60b9acSAndroid Build Coastguard Worker 					pt->ws.tx_draining_ext_list;
1694*1c60b9acSAndroid Build Coastguard Worker 			pt->ws.tx_draining_ext_list = wsi;
1695*1c60b9acSAndroid Build Coastguard Worker 			/* we must come back to do more */
1696*1c60b9acSAndroid Build Coastguard Worker 			lws_callback_on_writable(wsi);
1697*1c60b9acSAndroid Build Coastguard Worker 			/*
1698*1c60b9acSAndroid Build Coastguard Worker 			 * keep a copy of the write type for the overall
1699*1c60b9acSAndroid Build Coastguard Worker 			 * action that has provoked generation of these
1700*1c60b9acSAndroid Build Coastguard Worker 			 * fragments, so the last guy can use its FIN state.
1701*1c60b9acSAndroid Build Coastguard Worker 			 */
1702*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->tx_draining_stashed_wp = (uint8_t)*wp;
1703*1c60b9acSAndroid Build Coastguard Worker 			/*
1704*1c60b9acSAndroid Build Coastguard Worker 			 * Despite what we may have thought, this is definitely
1705*1c60b9acSAndroid Build Coastguard Worker 			 * NOT the last fragment, because the extension asserted
1706*1c60b9acSAndroid Build Coastguard Worker 			 * he has more coming.  For example, the extension may
1707*1c60b9acSAndroid Build Coastguard Worker 			 * be compressing, and has saved up everything until the
1708*1c60b9acSAndroid Build Coastguard Worker 			 * end, where the output is larger than one chunk.
1709*1c60b9acSAndroid Build Coastguard Worker 			 *
1710*1c60b9acSAndroid Build Coastguard Worker 			 * Make sure this intermediate one doesn't actually
1711*1c60b9acSAndroid Build Coastguard Worker 			 * go out with a FIN.
1712*1c60b9acSAndroid Build Coastguard Worker 			 */
1713*1c60b9acSAndroid Build Coastguard Worker 			*wp |= LWS_WRITE_NO_FIN;
1714*1c60b9acSAndroid Build Coastguard Worker 		}
1715*1c60b9acSAndroid Build Coastguard Worker #endif
1716*1c60b9acSAndroid Build Coastguard Worker 		if (pmdrx.eb_out.len && wsi->ws->stashed_write_pending) {
1717*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->stashed_write_pending = 0;
1718*1c60b9acSAndroid Build Coastguard Worker 			*wp = (unsigned int)(((*wp) & 0xc0) | (unsigned int)wsi->ws->stashed_write_type);
1719*1c60b9acSAndroid Build Coastguard Worker 		}
1720*1c60b9acSAndroid Build Coastguard Worker 	}
1721*1c60b9acSAndroid Build Coastguard Worker 
1722*1c60b9acSAndroid Build Coastguard Worker 	/*
1723*1c60b9acSAndroid Build Coastguard Worker 	 * an extension did something we need to keep... for example, if
1724*1c60b9acSAndroid Build Coastguard Worker 	 * compression extension, it has already updated its state according
1725*1c60b9acSAndroid Build Coastguard Worker 	 * to this being issued
1726*1c60b9acSAndroid Build Coastguard Worker 	 */
1727*1c60b9acSAndroid Build Coastguard Worker 	if (buf != pmdrx.eb_out.token) {
1728*1c60b9acSAndroid Build Coastguard Worker 		/*
1729*1c60b9acSAndroid Build Coastguard Worker 		 * ext might eat it, but not have anything to issue yet.
1730*1c60b9acSAndroid Build Coastguard Worker 		 * In that case we have to follow his lead, but stash and
1731*1c60b9acSAndroid Build Coastguard Worker 		 * replace the write type that was lost here the first time.
1732*1c60b9acSAndroid Build Coastguard Worker 		 */
1733*1c60b9acSAndroid Build Coastguard Worker 		if (len && !pmdrx.eb_out.len) {
1734*1c60b9acSAndroid Build Coastguard Worker 			if (!wsi->ws->stashed_write_pending)
1735*1c60b9acSAndroid Build Coastguard Worker 				wsi->ws->stashed_write_type =
1736*1c60b9acSAndroid Build Coastguard Worker 						(char)(*wp) & 0x3f;
1737*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->stashed_write_pending = 1;
1738*1c60b9acSAndroid Build Coastguard Worker 			return (int)len;
1739*1c60b9acSAndroid Build Coastguard Worker 		}
1740*1c60b9acSAndroid Build Coastguard Worker 		/*
1741*1c60b9acSAndroid Build Coastguard Worker 		 * extension recreated it:
1742*1c60b9acSAndroid Build Coastguard Worker 		 * need to buffer this if not all sent
1743*1c60b9acSAndroid Build Coastguard Worker 		 */
1744*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->clean_buffer = 0;
1745*1c60b9acSAndroid Build Coastguard Worker 	}
1746*1c60b9acSAndroid Build Coastguard Worker 
1747*1c60b9acSAndroid Build Coastguard Worker 	buf = pmdrx.eb_out.token;
1748*1c60b9acSAndroid Build Coastguard Worker 	len = (unsigned int)pmdrx.eb_out.len;
1749*1c60b9acSAndroid Build Coastguard Worker 
1750*1c60b9acSAndroid Build Coastguard Worker 	if (!buf) {
1751*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("null buf (%d)\n", (int)len);
1752*1c60b9acSAndroid Build Coastguard Worker 		return -1;
1753*1c60b9acSAndroid Build Coastguard Worker 	}
1754*1c60b9acSAndroid Build Coastguard Worker 
1755*1c60b9acSAndroid Build Coastguard Worker 	switch (wsi->ws->ietf_spec_revision) {
1756*1c60b9acSAndroid Build Coastguard Worker 	case 13:
1757*1c60b9acSAndroid Build Coastguard Worker 		if (masked7) {
1758*1c60b9acSAndroid Build Coastguard Worker 			pre += 4;
1759*1c60b9acSAndroid Build Coastguard Worker 			dropmask = &buf[0 - pre];
1760*1c60b9acSAndroid Build Coastguard Worker 			is_masked_bit = 0x80;
1761*1c60b9acSAndroid Build Coastguard Worker 		}
1762*1c60b9acSAndroid Build Coastguard Worker 
1763*1c60b9acSAndroid Build Coastguard Worker 		switch ((*wp) & 0xf) {
1764*1c60b9acSAndroid Build Coastguard Worker 		case LWS_WRITE_TEXT:
1765*1c60b9acSAndroid Build Coastguard Worker 			n = LWSWSOPC_TEXT_FRAME;
1766*1c60b9acSAndroid Build Coastguard Worker 			break;
1767*1c60b9acSAndroid Build Coastguard Worker 		case LWS_WRITE_BINARY:
1768*1c60b9acSAndroid Build Coastguard Worker 			n = LWSWSOPC_BINARY_FRAME;
1769*1c60b9acSAndroid Build Coastguard Worker 			break;
1770*1c60b9acSAndroid Build Coastguard Worker 		case LWS_WRITE_CONTINUATION:
1771*1c60b9acSAndroid Build Coastguard Worker 			n = LWSWSOPC_CONTINUATION;
1772*1c60b9acSAndroid Build Coastguard Worker 			break;
1773*1c60b9acSAndroid Build Coastguard Worker 
1774*1c60b9acSAndroid Build Coastguard Worker 		case LWS_WRITE_CLOSE:
1775*1c60b9acSAndroid Build Coastguard Worker 			n = LWSWSOPC_CLOSE;
1776*1c60b9acSAndroid Build Coastguard Worker 			break;
1777*1c60b9acSAndroid Build Coastguard Worker 		case LWS_WRITE_PING:
1778*1c60b9acSAndroid Build Coastguard Worker 			n = LWSWSOPC_PING;
1779*1c60b9acSAndroid Build Coastguard Worker 			break;
1780*1c60b9acSAndroid Build Coastguard Worker 		case LWS_WRITE_PONG:
1781*1c60b9acSAndroid Build Coastguard Worker 			n = LWSWSOPC_PONG;
1782*1c60b9acSAndroid Build Coastguard Worker 			break;
1783*1c60b9acSAndroid Build Coastguard Worker 		default:
1784*1c60b9acSAndroid Build Coastguard Worker 			lwsl_warn("lws_write: unknown write opc / wp\n");
1785*1c60b9acSAndroid Build Coastguard Worker 			return -1;
1786*1c60b9acSAndroid Build Coastguard Worker 		}
1787*1c60b9acSAndroid Build Coastguard Worker 
1788*1c60b9acSAndroid Build Coastguard Worker 		if (!((*wp) & LWS_WRITE_NO_FIN))
1789*1c60b9acSAndroid Build Coastguard Worker 			n |= 1 << 7;
1790*1c60b9acSAndroid Build Coastguard Worker 
1791*1c60b9acSAndroid Build Coastguard Worker 		if (len < 126) {
1792*1c60b9acSAndroid Build Coastguard Worker 			pre += 2;
1793*1c60b9acSAndroid Build Coastguard Worker 			buf[-pre] = (uint8_t)n;
1794*1c60b9acSAndroid Build Coastguard Worker 			buf[-pre + 1] = (unsigned char)(len | is_masked_bit);
1795*1c60b9acSAndroid Build Coastguard Worker 		} else {
1796*1c60b9acSAndroid Build Coastguard Worker 			if (len < 65536) {
1797*1c60b9acSAndroid Build Coastguard Worker 				pre += 4;
1798*1c60b9acSAndroid Build Coastguard Worker 				buf[-pre] = (uint8_t)n;
1799*1c60b9acSAndroid Build Coastguard Worker 				buf[-pre + 1] = (uint8_t)(126 | is_masked_bit);
1800*1c60b9acSAndroid Build Coastguard Worker 				buf[-pre + 2] = (unsigned char)(len >> 8);
1801*1c60b9acSAndroid Build Coastguard Worker 				buf[-pre + 3] = (unsigned char)len;
1802*1c60b9acSAndroid Build Coastguard Worker 			} else {
1803*1c60b9acSAndroid Build Coastguard Worker 				pre += 10;
1804*1c60b9acSAndroid Build Coastguard Worker 				buf[-pre] = (uint8_t)n;
1805*1c60b9acSAndroid Build Coastguard Worker 				buf[-pre + 1] = (uint8_t)(127 | is_masked_bit);
1806*1c60b9acSAndroid Build Coastguard Worker #if defined __LP64__
1807*1c60b9acSAndroid Build Coastguard Worker 					buf[-pre + 2] = (len >> 56) & 0x7f;
1808*1c60b9acSAndroid Build Coastguard Worker 					buf[-pre + 3] = (uint8_t)(len >> 48);
1809*1c60b9acSAndroid Build Coastguard Worker 					buf[-pre + 4] = (uint8_t)(len >> 40);
1810*1c60b9acSAndroid Build Coastguard Worker 					buf[-pre + 5] = (uint8_t)(len >> 32);
1811*1c60b9acSAndroid Build Coastguard Worker #else
1812*1c60b9acSAndroid Build Coastguard Worker 					buf[-pre + 2] = 0;
1813*1c60b9acSAndroid Build Coastguard Worker 					buf[-pre + 3] = 0;
1814*1c60b9acSAndroid Build Coastguard Worker 					buf[-pre + 4] = 0;
1815*1c60b9acSAndroid Build Coastguard Worker 					buf[-pre + 5] = 0;
1816*1c60b9acSAndroid Build Coastguard Worker #endif
1817*1c60b9acSAndroid Build Coastguard Worker 				buf[-pre + 6] = (unsigned char)(len >> 24);
1818*1c60b9acSAndroid Build Coastguard Worker 				buf[-pre + 7] = (unsigned char)(len >> 16);
1819*1c60b9acSAndroid Build Coastguard Worker 				buf[-pre + 8] = (unsigned char)(len >> 8);
1820*1c60b9acSAndroid Build Coastguard Worker 				buf[-pre + 9] = (unsigned char)len;
1821*1c60b9acSAndroid Build Coastguard Worker 			}
1822*1c60b9acSAndroid Build Coastguard Worker 		}
1823*1c60b9acSAndroid Build Coastguard Worker 		break;
1824*1c60b9acSAndroid Build Coastguard Worker 	}
1825*1c60b9acSAndroid Build Coastguard Worker 
1826*1c60b9acSAndroid Build Coastguard Worker do_more_inside_frame:
1827*1c60b9acSAndroid Build Coastguard Worker 
1828*1c60b9acSAndroid Build Coastguard Worker 	/*
1829*1c60b9acSAndroid Build Coastguard Worker 	 * Deal with masking if we are in client -> server direction and
1830*1c60b9acSAndroid Build Coastguard Worker 	 * the wp demands it
1831*1c60b9acSAndroid Build Coastguard Worker 	 */
1832*1c60b9acSAndroid Build Coastguard Worker 
1833*1c60b9acSAndroid Build Coastguard Worker 	if (masked7) {
1834*1c60b9acSAndroid Build Coastguard Worker 		if (!wsi->ws->inside_frame)
1835*1c60b9acSAndroid Build Coastguard Worker 			if (lws_0405_frame_mask_generate(wsi)) {
1836*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("frame mask generation failed\n");
1837*1c60b9acSAndroid Build Coastguard Worker 				return -1;
1838*1c60b9acSAndroid Build Coastguard Worker 			}
1839*1c60b9acSAndroid Build Coastguard Worker 
1840*1c60b9acSAndroid Build Coastguard Worker 		/*
1841*1c60b9acSAndroid Build Coastguard Worker 		 * in v7, just mask the payload
1842*1c60b9acSAndroid Build Coastguard Worker 		 */
1843*1c60b9acSAndroid Build Coastguard Worker 		if (dropmask) { /* never set if already inside frame */
1844*1c60b9acSAndroid Build Coastguard Worker 			for (n = 4; n < (int)len + 4; n++)
1845*1c60b9acSAndroid Build Coastguard Worker 				dropmask[n] = dropmask[n] ^ wsi->ws->mask[
1846*1c60b9acSAndroid Build Coastguard Worker 					(wsi->ws->mask_idx++) & 3];
1847*1c60b9acSAndroid Build Coastguard Worker 
1848*1c60b9acSAndroid Build Coastguard Worker 			/* copy the frame nonce into place */
1849*1c60b9acSAndroid Build Coastguard Worker 			memcpy(dropmask, wsi->ws->mask, 4);
1850*1c60b9acSAndroid Build Coastguard Worker 		}
1851*1c60b9acSAndroid Build Coastguard Worker 	}
1852*1c60b9acSAndroid Build Coastguard Worker 
1853*1c60b9acSAndroid Build Coastguard Worker 	if (lwsi_role_h2_ENCAPSULATION(wsi)) {
1854*1c60b9acSAndroid Build Coastguard Worker 		struct lws *encap = lws_get_network_wsi(wsi);
1855*1c60b9acSAndroid Build Coastguard Worker 
1856*1c60b9acSAndroid Build Coastguard Worker 		assert(encap != wsi);
1857*1c60b9acSAndroid Build Coastguard Worker 
1858*1c60b9acSAndroid Build Coastguard Worker 		return lws_rops_func_fidx(encap->role_ops,
1859*1c60b9acSAndroid Build Coastguard Worker 				   LWS_ROPS_write_role_protocol).
1860*1c60b9acSAndroid Build Coastguard Worker 					write_role_protocol(wsi, buf - pre,
1861*1c60b9acSAndroid Build Coastguard Worker 							    len + (unsigned int)pre, wp);
1862*1c60b9acSAndroid Build Coastguard Worker 	}
1863*1c60b9acSAndroid Build Coastguard Worker 
1864*1c60b9acSAndroid Build Coastguard Worker 	switch ((*wp) & 0x1f) {
1865*1c60b9acSAndroid Build Coastguard Worker 	case LWS_WRITE_TEXT:
1866*1c60b9acSAndroid Build Coastguard Worker 	case LWS_WRITE_BINARY:
1867*1c60b9acSAndroid Build Coastguard Worker 	case LWS_WRITE_CONTINUATION:
1868*1c60b9acSAndroid Build Coastguard Worker 		if (!wsi->h2_stream_carries_ws) {
1869*1c60b9acSAndroid Build Coastguard Worker 
1870*1c60b9acSAndroid Build Coastguard Worker 			/*
1871*1c60b9acSAndroid Build Coastguard Worker 			 * give any active extensions a chance to munge the
1872*1c60b9acSAndroid Build Coastguard Worker 			 * buffer before send.  We pass in a pointer to an
1873*1c60b9acSAndroid Build Coastguard Worker 			 * lws_tokens struct prepared with the default buffer
1874*1c60b9acSAndroid Build Coastguard Worker 			 * and content length that's in there.  Rather than
1875*1c60b9acSAndroid Build Coastguard Worker 			 * rewrite the default buffer, extensions that expect
1876*1c60b9acSAndroid Build Coastguard Worker 			 * to grow the buffer can adapt .token to point to their
1877*1c60b9acSAndroid Build Coastguard Worker 			 * own per-connection buffer in the extension user
1878*1c60b9acSAndroid Build Coastguard Worker 			 * allocation.  By default with no extensions or no
1879*1c60b9acSAndroid Build Coastguard Worker 			 * extension callback handling, just the normal input
1880*1c60b9acSAndroid Build Coastguard Worker 			 * buffer is used then so it is efficient.
1881*1c60b9acSAndroid Build Coastguard Worker 			 *
1882*1c60b9acSAndroid Build Coastguard Worker 			 * callback returns 1 in case it wants to spill more
1883*1c60b9acSAndroid Build Coastguard Worker 			 * buffers
1884*1c60b9acSAndroid Build Coastguard Worker 			 *
1885*1c60b9acSAndroid Build Coastguard Worker 			 * This takes care of holding the buffer if send is
1886*1c60b9acSAndroid Build Coastguard Worker 			 * incomplete, ie, if wsi->ws->clean_buffer is 0
1887*1c60b9acSAndroid Build Coastguard Worker 			 * (meaning an extension meddled with the buffer).  If
1888*1c60b9acSAndroid Build Coastguard Worker 			 * wsi->ws->clean_buffer is 1, it will instead return
1889*1c60b9acSAndroid Build Coastguard Worker 			 * to the user code how much OF THE USER BUFFER was
1890*1c60b9acSAndroid Build Coastguard Worker 			 * consumed.
1891*1c60b9acSAndroid Build Coastguard Worker 			 */
1892*1c60b9acSAndroid Build Coastguard Worker 
1893*1c60b9acSAndroid Build Coastguard Worker 			n = lws_issue_raw_ext_access(wsi, buf - pre, len + (unsigned int)pre);
1894*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->inside_frame = 1;
1895*1c60b9acSAndroid Build Coastguard Worker 			if (n <= 0)
1896*1c60b9acSAndroid Build Coastguard Worker 				return n;
1897*1c60b9acSAndroid Build Coastguard Worker 
1898*1c60b9acSAndroid Build Coastguard Worker 			if (n == (int)len + pre) {
1899*1c60b9acSAndroid Build Coastguard Worker 				/* everything in the buffer was handled
1900*1c60b9acSAndroid Build Coastguard Worker 				 * (or rebuffered...) */
1901*1c60b9acSAndroid Build Coastguard Worker 				wsi->ws->inside_frame = 0;
1902*1c60b9acSAndroid Build Coastguard Worker 				return (int)orig_len;
1903*1c60b9acSAndroid Build Coastguard Worker 			}
1904*1c60b9acSAndroid Build Coastguard Worker 
1905*1c60b9acSAndroid Build Coastguard Worker 			/*
1906*1c60b9acSAndroid Build Coastguard Worker 			 * it is how many bytes of user buffer got sent... may
1907*1c60b9acSAndroid Build Coastguard Worker 			 * be < orig_len in which case callback when writable
1908*1c60b9acSAndroid Build Coastguard Worker 			 * has already been arranged and user code can call
1909*1c60b9acSAndroid Build Coastguard Worker 			 * lws_write() again with the rest later.
1910*1c60b9acSAndroid Build Coastguard Worker 			 */
1911*1c60b9acSAndroid Build Coastguard Worker 
1912*1c60b9acSAndroid Build Coastguard Worker 			return n - pre;
1913*1c60b9acSAndroid Build Coastguard Worker 		}
1914*1c60b9acSAndroid Build Coastguard Worker 		break;
1915*1c60b9acSAndroid Build Coastguard Worker 	default:
1916*1c60b9acSAndroid Build Coastguard Worker 		break;
1917*1c60b9acSAndroid Build Coastguard Worker 	}
1918*1c60b9acSAndroid Build Coastguard Worker 
1919*1c60b9acSAndroid Build Coastguard Worker send_raw:
1920*1c60b9acSAndroid Build Coastguard Worker 	return lws_issue_raw(wsi, (unsigned char *)buf - pre, len + (unsigned int)pre);
1921*1c60b9acSAndroid Build Coastguard Worker }
1922*1c60b9acSAndroid Build Coastguard Worker 
1923*1c60b9acSAndroid Build Coastguard Worker static int
rops_close_kill_connection_ws(struct lws * wsi,enum lws_close_status reason)1924*1c60b9acSAndroid Build Coastguard Worker rops_close_kill_connection_ws(struct lws *wsi, enum lws_close_status reason)
1925*1c60b9acSAndroid Build Coastguard Worker {
1926*1c60b9acSAndroid Build Coastguard Worker 	/* deal with ws encapsulation in h2 */
1927*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
1928*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->mux_substream && wsi->h2_stream_carries_ws)
1929*1c60b9acSAndroid Build Coastguard Worker 		return lws_rops_func_fidx(&role_ops_h2,
1930*1c60b9acSAndroid Build Coastguard Worker 				   LWS_ROPS_close_kill_connection).
1931*1c60b9acSAndroid Build Coastguard Worker 				close_kill_connection(wsi, reason);
1932*1c60b9acSAndroid Build Coastguard Worker 
1933*1c60b9acSAndroid Build Coastguard Worker 	return 0;
1934*1c60b9acSAndroid Build Coastguard Worker #else
1935*1c60b9acSAndroid Build Coastguard Worker 	return 0;
1936*1c60b9acSAndroid Build Coastguard Worker #endif
1937*1c60b9acSAndroid Build Coastguard Worker }
1938*1c60b9acSAndroid Build Coastguard Worker 
1939*1c60b9acSAndroid Build Coastguard Worker static int
rops_callback_on_writable_ws(struct lws * wsi)1940*1c60b9acSAndroid Build Coastguard Worker rops_callback_on_writable_ws(struct lws *wsi)
1941*1c60b9acSAndroid Build Coastguard Worker {
1942*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
1943*1c60b9acSAndroid Build Coastguard Worker 	if (lwsi_role_h2_ENCAPSULATION(wsi)) {
1944*1c60b9acSAndroid Build Coastguard Worker 		/* we know then that it has an h2 parent */
1945*1c60b9acSAndroid Build Coastguard Worker 		struct lws *enc = lws_rops_func_fidx(&role_ops_h2,
1946*1c60b9acSAndroid Build Coastguard Worker 						     LWS_ROPS_encapsulation_parent).
1947*1c60b9acSAndroid Build Coastguard Worker 						     encapsulation_parent(wsi);
1948*1c60b9acSAndroid Build Coastguard Worker 
1949*1c60b9acSAndroid Build Coastguard Worker 		assert(enc);
1950*1c60b9acSAndroid Build Coastguard Worker 		if (lws_rops_func_fidx(enc->role_ops,
1951*1c60b9acSAndroid Build Coastguard Worker 				       LWS_ROPS_callback_on_writable).
1952*1c60b9acSAndroid Build Coastguard Worker 						callback_on_writable(wsi))
1953*1c60b9acSAndroid Build Coastguard Worker 			return 1;
1954*1c60b9acSAndroid Build Coastguard Worker 	}
1955*1c60b9acSAndroid Build Coastguard Worker #endif
1956*1c60b9acSAndroid Build Coastguard Worker 	return 0;
1957*1c60b9acSAndroid Build Coastguard Worker }
1958*1c60b9acSAndroid Build Coastguard Worker 
1959*1c60b9acSAndroid Build Coastguard Worker static int
rops_init_vhost_ws(struct lws_vhost * vh,const struct lws_context_creation_info * info)1960*1c60b9acSAndroid Build Coastguard Worker rops_init_vhost_ws(struct lws_vhost *vh,
1961*1c60b9acSAndroid Build Coastguard Worker 		   const struct lws_context_creation_info *info)
1962*1c60b9acSAndroid Build Coastguard Worker {
1963*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
1964*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_PLUGINS
1965*1c60b9acSAndroid Build Coastguard Worker 	struct lws_plugin *plugin;
1966*1c60b9acSAndroid Build Coastguard Worker 	int m;
1967*1c60b9acSAndroid Build Coastguard Worker 
1968*1c60b9acSAndroid Build Coastguard Worker 	if (vh->context->plugin_extension_count) {
1969*1c60b9acSAndroid Build Coastguard Worker 
1970*1c60b9acSAndroid Build Coastguard Worker 		m = 0;
1971*1c60b9acSAndroid Build Coastguard Worker 		while (info->extensions && info->extensions[m].callback)
1972*1c60b9acSAndroid Build Coastguard Worker 			m++;
1973*1c60b9acSAndroid Build Coastguard Worker 
1974*1c60b9acSAndroid Build Coastguard Worker 		/*
1975*1c60b9acSAndroid Build Coastguard Worker 		 * give the vhost a unified list of extensions including the
1976*1c60b9acSAndroid Build Coastguard Worker 		 * ones that came from plugins
1977*1c60b9acSAndroid Build Coastguard Worker 		 */
1978*1c60b9acSAndroid Build Coastguard Worker 		vh->ws.extensions = lws_zalloc(sizeof(struct lws_extension) *
1979*1c60b9acSAndroid Build Coastguard Worker 				     (unsigned int)(m + vh->context->plugin_extension_count + 1),
1980*1c60b9acSAndroid Build Coastguard Worker 				     "extensions");
1981*1c60b9acSAndroid Build Coastguard Worker 		if (!vh->ws.extensions)
1982*1c60b9acSAndroid Build Coastguard Worker 			return 1;
1983*1c60b9acSAndroid Build Coastguard Worker 
1984*1c60b9acSAndroid Build Coastguard Worker 		memcpy((struct lws_extension *)vh->ws.extensions, info->extensions,
1985*1c60b9acSAndroid Build Coastguard Worker 		       sizeof(struct lws_extension) * (unsigned int)m);
1986*1c60b9acSAndroid Build Coastguard Worker 		plugin = vh->context->plugin_list;
1987*1c60b9acSAndroid Build Coastguard Worker 		while (plugin) {
1988*1c60b9acSAndroid Build Coastguard Worker 			const lws_plugin_protocol_t *plpr =
1989*1c60b9acSAndroid Build Coastguard Worker 				(const lws_plugin_protocol_t *)plugin->hdr;
1990*1c60b9acSAndroid Build Coastguard Worker 
1991*1c60b9acSAndroid Build Coastguard Worker 			memcpy((struct lws_extension *)&vh->ws.extensions[m],
1992*1c60b9acSAndroid Build Coastguard Worker 				plpr->extensions,
1993*1c60b9acSAndroid Build Coastguard Worker 			       sizeof(struct lws_extension) *
1994*1c60b9acSAndroid Build Coastguard Worker 			       (unsigned int)plpr->count_extensions);
1995*1c60b9acSAndroid Build Coastguard Worker 			m += plpr->count_extensions;
1996*1c60b9acSAndroid Build Coastguard Worker 			plugin = plugin->list;
1997*1c60b9acSAndroid Build Coastguard Worker 		}
1998*1c60b9acSAndroid Build Coastguard Worker 	} else
1999*1c60b9acSAndroid Build Coastguard Worker #endif
2000*1c60b9acSAndroid Build Coastguard Worker 		vh->ws.extensions = info->extensions;
2001*1c60b9acSAndroid Build Coastguard Worker #endif
2002*1c60b9acSAndroid Build Coastguard Worker 
2003*1c60b9acSAndroid Build Coastguard Worker 	return 0;
2004*1c60b9acSAndroid Build Coastguard Worker }
2005*1c60b9acSAndroid Build Coastguard Worker 
2006*1c60b9acSAndroid Build Coastguard Worker static int
rops_destroy_vhost_ws(struct lws_vhost * vh)2007*1c60b9acSAndroid Build Coastguard Worker rops_destroy_vhost_ws(struct lws_vhost *vh)
2008*1c60b9acSAndroid Build Coastguard Worker {
2009*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_PLUGINS
2010*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
2011*1c60b9acSAndroid Build Coastguard Worker 	if (vh->context->plugin_extension_count)
2012*1c60b9acSAndroid Build Coastguard Worker 		lws_free((void *)vh->ws.extensions);
2013*1c60b9acSAndroid Build Coastguard Worker #endif
2014*1c60b9acSAndroid Build Coastguard Worker #endif
2015*1c60b9acSAndroid Build Coastguard Worker 
2016*1c60b9acSAndroid Build Coastguard Worker 	return 0;
2017*1c60b9acSAndroid Build Coastguard Worker }
2018*1c60b9acSAndroid Build Coastguard Worker 
2019*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_PROXY)
2020*1c60b9acSAndroid Build Coastguard Worker static int
ws_destroy_proxy_buf(struct lws_dll2 * d,void * user)2021*1c60b9acSAndroid Build Coastguard Worker ws_destroy_proxy_buf(struct lws_dll2 *d, void *user)
2022*1c60b9acSAndroid Build Coastguard Worker {
2023*1c60b9acSAndroid Build Coastguard Worker 	lws_free(d);
2024*1c60b9acSAndroid Build Coastguard Worker 
2025*1c60b9acSAndroid Build Coastguard Worker 	return 0;
2026*1c60b9acSAndroid Build Coastguard Worker }
2027*1c60b9acSAndroid Build Coastguard Worker #endif
2028*1c60b9acSAndroid Build Coastguard Worker 
2029*1c60b9acSAndroid Build Coastguard Worker static int
rops_destroy_role_ws(struct lws * wsi)2030*1c60b9acSAndroid Build Coastguard Worker rops_destroy_role_ws(struct lws *wsi)
2031*1c60b9acSAndroid Build Coastguard Worker {
2032*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_PROXY)
2033*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_foreach_safe(&wsi->ws->proxy_owner, NULL, ws_destroy_proxy_buf);
2034*1c60b9acSAndroid Build Coastguard Worker #endif
2035*1c60b9acSAndroid Build Coastguard Worker 
2036*1c60b9acSAndroid Build Coastguard Worker 	lws_free_set_NULL(wsi->ws);
2037*1c60b9acSAndroid Build Coastguard Worker 
2038*1c60b9acSAndroid Build Coastguard Worker 	return 0;
2039*1c60b9acSAndroid Build Coastguard Worker }
2040*1c60b9acSAndroid Build Coastguard Worker 
2041*1c60b9acSAndroid Build Coastguard Worker static int
rops_issue_keepalive_ws(struct lws * wsi,int isvalid)2042*1c60b9acSAndroid Build Coastguard Worker rops_issue_keepalive_ws(struct lws *wsi, int isvalid)
2043*1c60b9acSAndroid Build Coastguard Worker {
2044*1c60b9acSAndroid Build Coastguard Worker 	uint64_t us;
2045*1c60b9acSAndroid Build Coastguard Worker 
2046*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
2047*1c60b9acSAndroid Build Coastguard Worker 	if (lwsi_role_h2_ENCAPSULATION(wsi)) {
2048*1c60b9acSAndroid Build Coastguard Worker 		/* we know then that it has an h2 parent */
2049*1c60b9acSAndroid Build Coastguard Worker 		struct lws *enc = lws_rops_func_fidx(&role_ops_h2,
2050*1c60b9acSAndroid Build Coastguard Worker 						     LWS_ROPS_encapsulation_parent).
2051*1c60b9acSAndroid Build Coastguard Worker 						     encapsulation_parent(wsi);
2052*1c60b9acSAndroid Build Coastguard Worker 
2053*1c60b9acSAndroid Build Coastguard Worker 		assert(enc);
2054*1c60b9acSAndroid Build Coastguard Worker 		if (lws_rops_func_fidx(enc->role_ops, LWS_ROPS_issue_keepalive).
2055*1c60b9acSAndroid Build Coastguard Worker 						  issue_keepalive(enc, isvalid))
2056*1c60b9acSAndroid Build Coastguard Worker 			return 1;
2057*1c60b9acSAndroid Build Coastguard Worker 	}
2058*1c60b9acSAndroid Build Coastguard Worker #endif
2059*1c60b9acSAndroid Build Coastguard Worker 
2060*1c60b9acSAndroid Build Coastguard Worker 	if (isvalid)
2061*1c60b9acSAndroid Build Coastguard Worker 		_lws_validity_confirmed_role(wsi);
2062*1c60b9acSAndroid Build Coastguard Worker 	else {
2063*1c60b9acSAndroid Build Coastguard Worker 		us = (uint64_t)lws_now_usecs();
2064*1c60b9acSAndroid Build Coastguard Worker 		memcpy(&wsi->ws->ping_payload_buf[LWS_PRE], &us, 8);
2065*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->send_check_ping = 1;
2066*1c60b9acSAndroid Build Coastguard Worker 		lws_callback_on_writable(wsi);
2067*1c60b9acSAndroid Build Coastguard Worker 	}
2068*1c60b9acSAndroid Build Coastguard Worker 
2069*1c60b9acSAndroid Build Coastguard Worker 	return 0;
2070*1c60b9acSAndroid Build Coastguard Worker }
2071*1c60b9acSAndroid Build Coastguard Worker 
2072*1c60b9acSAndroid Build Coastguard Worker static const lws_rops_t rops_table_ws[] = {
2073*1c60b9acSAndroid Build Coastguard Worker 	/*  1 */ { .init_vhost		    = rops_init_vhost_ws },
2074*1c60b9acSAndroid Build Coastguard Worker 	/*  2 */ { .destroy_vhost	    = rops_destroy_vhost_ws },
2075*1c60b9acSAndroid Build Coastguard Worker 	/*  3 */ { .service_flag_pending    = rops_service_flag_pending_ws },
2076*1c60b9acSAndroid Build Coastguard Worker 	/*  4 */ { .handle_POLLIN	    = rops_handle_POLLIN_ws },
2077*1c60b9acSAndroid Build Coastguard Worker 	/*  5 */ { .handle_POLLOUT	    = rops_handle_POLLOUT_ws },
2078*1c60b9acSAndroid Build Coastguard Worker 	/*  6 */ { .callback_on_writable    = rops_callback_on_writable_ws },
2079*1c60b9acSAndroid Build Coastguard Worker 	/*  7 */ { .write_role_protocol	    = rops_write_role_protocol_ws },
2080*1c60b9acSAndroid Build Coastguard Worker 	/*  8 */ { .close_via_role_protocol = rops_close_via_role_protocol_ws },
2081*1c60b9acSAndroid Build Coastguard Worker 	/*  9 */ { .close_role		    = rops_close_role_ws },
2082*1c60b9acSAndroid Build Coastguard Worker 	/* 10 */ { .close_kill_connection   = rops_close_kill_connection_ws },
2083*1c60b9acSAndroid Build Coastguard Worker 	/* 11 */ { .destroy_role	    = rops_destroy_role_ws },
2084*1c60b9acSAndroid Build Coastguard Worker 	/* 12 */ { .issue_keepalive	    = rops_issue_keepalive_ws },
2085*1c60b9acSAndroid Build Coastguard Worker };
2086*1c60b9acSAndroid Build Coastguard Worker 
2087*1c60b9acSAndroid Build Coastguard Worker const struct lws_role_ops role_ops_ws = {
2088*1c60b9acSAndroid Build Coastguard Worker 	/* role name */			"ws",
2089*1c60b9acSAndroid Build Coastguard Worker 	/* alpn id */			NULL,
2090*1c60b9acSAndroid Build Coastguard Worker 
2091*1c60b9acSAndroid Build Coastguard Worker 	/* rops_table */		rops_table_ws,
2092*1c60b9acSAndroid Build Coastguard Worker 	/* rops_idx */			{
2093*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_check_upgrades */
2094*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_pt_init_destroy */		0x00,
2095*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_init_vhost */
2096*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_destroy_vhost */			0x12,
2097*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_service_flag_pending */
2098*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_handle_POLLIN */			0x34,
2099*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_handle_POLLOUT */
2100*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_perform_user_POLLOUT */		0x50,
2101*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_callback_on_writable */
2102*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_tx_credit */			0x60,
2103*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_write_role_protocol */
2104*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_encapsulation_parent */		0x70,
2105*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_alpn_negotiated */
2106*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_close_via_role_protocol */	0x08,
2107*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_close_role */
2108*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_close_kill_connection */		0x9a,
2109*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_destroy_role */
2110*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_adoption_bind */			0xb0,
2111*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_client_bind */
2112*1c60b9acSAndroid Build Coastguard Worker 	  /* LWS_ROPS_issue_keepalive */		0x0c,
2113*1c60b9acSAndroid Build Coastguard Worker 					},
2114*1c60b9acSAndroid Build Coastguard Worker 
2115*1c60b9acSAndroid Build Coastguard Worker 	/* adoption_cb clnt, srv */	{ LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED,
2116*1c60b9acSAndroid Build Coastguard Worker 					  LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED },
2117*1c60b9acSAndroid Build Coastguard Worker 	/* rx_cb clnt, srv */		{ LWS_CALLBACK_CLIENT_RECEIVE,
2118*1c60b9acSAndroid Build Coastguard Worker 					  LWS_CALLBACK_RECEIVE },
2119*1c60b9acSAndroid Build Coastguard Worker 	/* writeable cb clnt, srv */	{ LWS_CALLBACK_CLIENT_WRITEABLE,
2120*1c60b9acSAndroid Build Coastguard Worker 					  LWS_CALLBACK_SERVER_WRITEABLE },
2121*1c60b9acSAndroid Build Coastguard Worker 	/* close cb clnt, srv */	{ LWS_CALLBACK_CLIENT_CLOSED,
2122*1c60b9acSAndroid Build Coastguard Worker 					  LWS_CALLBACK_CLOSED },
2123*1c60b9acSAndroid Build Coastguard Worker 	/* protocol_bind cb c, srv */	{ LWS_CALLBACK_WS_CLIENT_BIND_PROTOCOL,
2124*1c60b9acSAndroid Build Coastguard Worker 					  LWS_CALLBACK_WS_SERVER_BIND_PROTOCOL },
2125*1c60b9acSAndroid Build Coastguard Worker 	/* protocol_unbind cb c, srv */	{ LWS_CALLBACK_WS_CLIENT_DROP_PROTOCOL,
2126*1c60b9acSAndroid Build Coastguard Worker 					  LWS_CALLBACK_WS_SERVER_DROP_PROTOCOL },
2127*1c60b9acSAndroid Build Coastguard Worker 	/* file handles */		0
2128*1c60b9acSAndroid Build Coastguard Worker };
2129