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