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