2 * libwebsockets - small server side websockets and web server implementation
4 * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 #include <core/private.h>
24 #define LWS_CPYAPP(ptr, str) { strcpy(ptr, str); ptr += strlen(str); }
26 #if !defined(LWS_WITHOUT_EXTENSIONS)
28 lws_extension_server_handshake(struct lws *wsi, char **p, int budget)
30 struct lws_context *context = wsi->context;
31 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
32 char ext_name[64], *args, *end = (*p) + budget - 1;
33 const struct lws_ext_options *opts, *po;
34 const struct lws_extension *ext;
35 struct lws_ext_option_arg oa;
42 * Figure out which extensions the client has that we want to
43 * enable on this connection, and give him back the list
45 if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS))
49 * break down the list of client extensions
53 if (lws_hdr_copy(wsi, (char *)pt->serv_buf, context->pt_serv_buf_size,
54 WSI_TOKEN_EXTENSIONS) < 0)
57 c = (char *)pt->serv_buf;
58 lwsl_parser("WSI_TOKEN_EXTENSIONS = '%s'\n", c);
59 wsi->ws->count_act_ext = 0;
65 * We may get a simple request
67 * Sec-WebSocket-Extensions: permessage-deflate
69 * or an elaborated one with requested options
71 * Sec-WebSocket-Extensions: permessage-deflate; \
72 * server_no_context_takeover; \
73 * client_no_context_takeover
78 if (c >= (char *)pt->serv_buf + 255)
81 if (*c && (*c != ',' && *c != '\t')) {
87 if (ignore || *c == ' ') {
92 if (n < (int)sizeof(ext_name) - 1)
107 while (args && *args == ' ')
110 /* check a client's extension against our support */
112 ext = wsi->vhost->ws.extensions;
114 while (ext && ext->callback) {
116 if (strcmp(ext_name, ext->name)) {
122 * oh, we do support this one he asked for... but let's
123 * confirm he only gave it once
125 for (m = 0; m < wsi->ws->count_act_ext; m++)
126 if (wsi->ws->active_extensions[m] == ext) {
127 lwsl_info("ext mentioned twice\n");
128 return 1; /* shenanigans */
132 * ask user code if it's OK to apply it on this
133 * particular connection + protocol
135 m = (wsi->protocol->callback)(wsi,
136 LWS_CALLBACK_CONFIRM_EXTENSION_OKAY,
137 wsi->user_space, ext_name, 0);
140 * zero return from callback means go ahead and allow
141 * the extension, it's what we get if the callback is
153 /* instantiate the extension on this conn */
155 wsi->ws->active_extensions[wsi->ws->count_act_ext] = ext;
157 /* allow him to construct his context */
159 if (ext->callback(lws_get_context(wsi), ext, wsi,
160 LWS_EXT_CB_CONSTRUCT,
161 (void *)&wsi->ws->act_ext_user[
162 wsi->ws->count_act_ext],
164 lwsl_info("ext %s failed construction\n",
176 "\x0d\x0aSec-WebSocket-Extensions: ");
177 *p += lws_snprintf(*p, (end - *p), "%s", ext_name);
180 * The client may send a bunch of different option
181 * sets for the same extension, we are supposed to
182 * pick one we like the look of. The option sets are
183 * separated by comma.
185 * Actually we just either accept the first one or
188 * Go through the options trying to apply the
192 lwsl_info("ext args %s\n", args);
194 while (args && *args && *args != ',') {
199 /* only support arg-less options... */
200 if (po->type != EXTARG_NONE ||
201 strncmp(args, po->name,
206 oa.option_name = NULL;
207 oa.option_index = (int)(po - opts);
210 lwsl_info("setting '%s'\n", po->name);
211 if (!ext->callback(lws_get_context(wsi),
213 LWS_EXT_CB_OPTION_SET,
214 wsi->ws->act_ext_user[
215 wsi->ws->count_act_ext],
218 *p += lws_snprintf(*p,
221 lwsl_debug("adding option %s\n",
226 while (*args && *args != ',' && *args != ';')
233 wsi->ws->count_act_ext++;
234 lwsl_parser("cnt_act_ext <- %d\n",
235 wsi->ws->count_act_ext);
237 if (args && *args == ',')
252 lws_process_ws_upgrade2(struct lws *wsi)
254 struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
255 const struct lws_protocol_vhost_options *pvos = NULL;
256 const char *ws_prot_basic_auth = NULL;
259 * Allow basic auth a look-in now we bound the wsi to the protocol.
261 * For vhost ws basic auth, it is "basic-auth": "path" as usual but
262 * applied to the protocol's entry in the vhost's "ws-protocols":
266 pvos = lws_vhost_protocol_options(wsi->vhost, wsi->protocol->name);
267 if (pvos && pvos->options &&
268 !lws_pvo_get_str((void *)pvos->options, "basic-auth",
269 &ws_prot_basic_auth)) {
270 lwsl_info("%s: ws upgrade requires basic auth\n", __func__);
271 switch(lws_check_basic_auth(wsi, ws_prot_basic_auth)) {
274 case LCBA_FAILED_AUTH:
275 return lws_unauthorised_basic_auth(wsi);
276 case LCBA_END_TRANSACTION:
277 lws_return_http_status(wsi, HTTP_STATUS_FORBIDDEN, NULL);
278 return lws_http_transaction_completed(wsi);
283 * We are upgrading to ws, so http/1.1 + h2 and keepalive + pipelined
284 * header considerations about keeping the ah around no longer apply.
286 * However it's common for the first ws protocol data to have been
287 * coalesced with the browser upgrade request and to already be in the
291 lws_pt_lock(pt, __func__);
293 if (!wsi->h2_stream_carries_ws)
294 lws_role_transition(wsi, LWSIFR_SERVER, LRS_ESTABLISHED,
299 /* allocate the ws struct for the wsi */
301 wsi->ws = lws_zalloc(sizeof(*wsi->ws), "ws struct");
303 lwsl_notice("OOM\n");
307 if (lws_hdr_total_length(wsi, WSI_TOKEN_VERSION))
308 wsi->ws->ietf_spec_revision =
309 atoi(lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION));
311 /* allocate wsi->user storage */
312 if (lws_ensure_user_space(wsi)) {
313 lwsl_notice("problem with user space\n");
318 * Give the user code a chance to study the request and
319 * have the opportunity to deny it
321 if ((wsi->protocol->callback)(wsi,
322 LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
324 lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL), 0)) {
325 lwsl_warn("User code denied connection\n");
330 * Perform the handshake according to the protocol version the
334 switch (wsi->ws->ietf_spec_revision) {
336 lwsl_notice("Unknown client spec version %d\n",
337 wsi->ws->ietf_spec_revision);
338 wsi->ws->ietf_spec_revision = 13;
342 #if defined(LWS_WITH_HTTP2)
343 if (wsi->h2_stream_carries_ws) {
344 if (lws_h2_ws_handshake(wsi)) {
345 lwsl_notice("h2 ws handshake failed\n");
348 lws_role_transition(wsi,
349 LWSIFR_SERVER | LWSIFR_P_ENCAP_H2,
350 LRS_ESTABLISHED, &role_ops_ws);
354 lwsl_parser("lws_parse calling handshake_04\n");
355 if (handshake_0405(wsi->context, wsi)) {
356 lwsl_notice("hs0405 has failed the connection\n");
363 lws_server_init_wsi_for_ws(wsi);
364 lwsl_parser("accepted v%02d connection\n", wsi->ws->ietf_spec_revision);
366 #if defined(LWS_WITH_ACCESS_LOG)
368 char *uptr = NULL, combo[128];
369 int l, meth = lws_http_get_uri_and_method(wsi, &uptr, &l);
371 if (wsi->h2_stream_carries_ws)
372 wsi->http.request_version = HTTP_VERSION_2;
374 wsi->http.access_log.response = 101;
376 l = lws_snprintf(combo, sizeof(combo), "%.*s (%s)", l, uptr,
377 wsi->protocol->name);
379 lws_prepare_access_log_info(wsi, combo, l, meth);
384 lwsl_info("%s: %p: dropping ah on ws upgrade\n", __func__, wsi);
385 lws_header_table_detach(wsi, 1);
391 lws_process_ws_upgrade(struct lws *wsi)
393 const struct lws_protocols *pcol = NULL;
394 char buf[128], name[64];
395 struct lws_tokenize ts;
399 lwsl_err("NULL protocol at lws_read\n");
402 * It's either websocket or h2->websocket
404 * If we are on h1, confirm we got the required "connection: upgrade"
405 * header. h2 / ws-over-h2 does not have this.
408 #if defined(LWS_WITH_HTTP2)
409 if (!wsi->http2_substream) {
412 lws_tokenize_init(&ts, buf, LWS_TOKENIZE_F_COMMA_SEP_LIST |
413 LWS_TOKENIZE_F_DOT_NONTERM |
414 LWS_TOKENIZE_F_RFC7230_DELIMS |
415 LWS_TOKENIZE_F_MINUS_NONTERM);
416 ts.len = lws_hdr_copy(wsi, buf, sizeof(buf) - 1,
417 WSI_TOKEN_CONNECTION);
419 goto bad_conn_format;
422 e = lws_tokenize(&ts);
424 case LWS_TOKZE_TOKEN:
425 if (!strncasecmp(ts.token, "upgrade", ts.token_len))
429 case LWS_TOKZE_DELIMITER:
432 default: /* includes ENDED */
434 lwsl_err("%s: malformed or absent conn hdr\n",
441 #if defined(LWS_WITH_HTTP2)
445 #if defined(LWS_WITH_HTTP_PROXY)
447 const struct lws_http_mount *hit;
448 int uri_len = 0, meth;
451 meth = lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len);
452 hit = lws_find_mount(wsi, uri_ptr, uri_len);
454 if (hit && (meth == 0 || meth == 8) &&
455 (hit->origin_protocol == LWSMPRO_HTTPS ||
456 hit->origin_protocol == LWSMPRO_HTTP))
458 * We are an h1 ws upgrade on a urlpath that corresponds
459 * to a proxying mount. Don't try to deal with it
460 * locally, eg, we won't even have the right protocol
461 * handler since we're not the guy handling it, just a
464 * Instead open the related ongoing h1 connection
465 * according to the mount configuration and proxy
466 * whatever that has to say from now on.
468 return lws_http_proxy_start(wsi, hit, uri_ptr, 1);
473 * Select the first protocol we support from the list
474 * the client sent us.
477 lws_tokenize_init(&ts, buf, LWS_TOKENIZE_F_COMMA_SEP_LIST |
478 LWS_TOKENIZE_F_MINUS_NONTERM |
479 LWS_TOKENIZE_F_DOT_NONTERM |
480 LWS_TOKENIZE_F_RFC7230_DELIMS);
481 ts.len = lws_hdr_copy(wsi, buf, sizeof(buf) - 1, WSI_TOKEN_PROTOCOL);
483 lwsl_err("%s: protocol list too long\n", __func__);
487 int n = wsi->vhost->default_protocol_index;
489 * Some clients only have one protocol and do not send the
490 * protocol list header... allow it and match to the vhost's
491 * default protocol (which itself defaults to zero).
493 * Setting the vhost default protocol index to -1 or anything
494 * more than the actual number of protocols on the vhost causes
495 * these "no protocol" ws connections to be rejected.
498 if (n >= wsi->vhost->count_protocols) {
499 lwsl_notice("%s: rejecting ws upg with no protocol\n",
505 lwsl_info("%s: defaulting to prot handler %d\n", __func__, n);
507 lws_bind_protocol(wsi, &wsi->vhost->protocols[n],
508 "ws upgrade default pcol");
513 /* otherwise go through the user-provided protocol list */
516 e = lws_tokenize(&ts);
518 case LWS_TOKZE_TOKEN:
520 if (lws_tokenize_cstr(&ts, name, sizeof(name))) {
521 lwsl_err("%s: pcol name too long\n", __func__);
525 lwsl_debug("checking %s\n", name);
526 pcol = lws_vhost_name_to_protocol(wsi->vhost, name);
528 /* if we know it, bind to it and stop looking */
529 lws_bind_protocol(wsi, pcol, "ws upg pcol");
534 case LWS_TOKZE_DELIMITER:
535 case LWS_TOKZE_ENDED:
539 lwsl_err("%s: malformatted protocol list", __func__);
545 /* we didn't find a protocol he wanted? */
548 lwsl_notice("No supported protocol \"%s\"\n", buf);
555 return lws_process_ws_upgrade2(wsi);
559 handshake_0405(struct lws_context *context, struct lws *wsi)
561 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
562 struct lws_process_html_args args;
563 unsigned char hash[20];
568 if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST) ||
569 !lws_hdr_total_length(wsi, WSI_TOKEN_KEY)) {
570 lwsl_info("handshake_04 missing pieces\n");
571 /* completed header processing, but missing some bits */
575 if (lws_hdr_total_length(wsi, WSI_TOKEN_KEY) >=
576 MAX_WEBSOCKET_04_KEY_LEN) {
577 lwsl_warn("Client key too long %d\n", MAX_WEBSOCKET_04_KEY_LEN);
582 * since key length is restricted above (currently 128), cannot
585 n = sprintf((char *)pt->serv_buf,
586 "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
587 lws_hdr_simple_ptr(wsi, WSI_TOKEN_KEY));
589 lws_SHA1(pt->serv_buf, n, hash);
591 accept_len = lws_b64_encode_string((char *)hash, 20,
592 (char *)pt->serv_buf, context->pt_serv_buf_size);
593 if (accept_len < 0) {
594 lwsl_warn("Base64 encoded hash too long\n");
598 /* allocate the per-connection user memory (if any) */
599 if (lws_ensure_user_space(wsi))
602 /* create the response packet */
604 /* make a buffer big enough for everything */
606 response = (char *)pt->serv_buf + MAX_WEBSOCKET_04_KEY_LEN +
609 LWS_CPYAPP(p, "HTTP/1.1 101 Switching Protocols\x0d\x0a"
610 "Upgrade: WebSocket\x0d\x0a"
611 "Connection: Upgrade\x0d\x0a"
612 "Sec-WebSocket-Accept: ");
613 strcpy(p, (char *)pt->serv_buf);
616 /* we can only return the protocol header if:
617 * - one came in, and ... */
618 if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL) &&
619 /* - it is not an empty string */
620 wsi->protocol->name &&
621 wsi->protocol->name[0]) {
622 const char *prot = wsi->protocol->name;
624 #if defined(LWS_WITH_HTTP_PROXY)
625 if (wsi->proxied_ws_parent && wsi->child_list)
626 prot = wsi->child_list->ws->actual_protocol;
629 LWS_CPYAPP(p, "\x0d\x0aSec-WebSocket-Protocol: ");
630 p += lws_snprintf(p, 128, "%s", prot);
633 #if !defined(LWS_WITHOUT_EXTENSIONS)
635 * Figure out which extensions the client has that we want to
636 * enable on this connection, and give him back the list.
638 * Give him a limited write bugdet
640 if (lws_extension_server_handshake(wsi, &p, 192))
643 LWS_CPYAPP(p, "\x0d\x0a");
646 args.max_len = lws_ptr_diff((char *)pt->serv_buf +
647 context->pt_serv_buf_size, p);
648 if (user_callback_handle_rxflow(wsi->protocol->callback, wsi,
649 LWS_CALLBACK_ADD_HEADERS,
650 wsi->user_space, &args, 0))
655 /* end of response packet */
657 LWS_CPYAPP(p, "\x0d\x0a");
659 /* okay send the handshake response accepting the connection */
661 lwsl_parser("issuing resp pkt %d len\n",
662 lws_ptr_diff(p, response));
664 fwrite(response, 1, p - response, stderr);
666 n = lws_write(wsi, (unsigned char *)response, p - response,
667 LWS_WRITE_HTTP_HEADERS);
668 if (n != (p - response)) {
669 lwsl_info("%s: ERROR writing to socket %d\n", __func__, n);
673 /* alright clean up and set ourselves into established state */
675 lwsi_set_state(wsi, LRS_ESTABLISHED);
676 wsi->lws_rx_parse_state = LWS_RXPS_NEW;
679 const char * uri_ptr =
680 lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI);
681 int uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI);
682 const struct lws_http_mount *hit =
683 lws_find_mount(wsi, uri_ptr, uri_len);
684 if (hit && hit->cgienv &&
685 wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_PMO,
686 wsi->user_space, (void *)hit->cgienv, 0))
693 /* caller will free up his parsing allocations */
700 * Once we reach LWS_RXPS_WS_FRAME_PAYLOAD, we know how much
701 * to expect in that state and can deal with it in bulk more efficiently.
705 lws_ws_frame_rest_is_payload(struct lws *wsi, uint8_t **buf, size_t len)
707 struct lws_ext_pm_deflate_rx_ebufs pmdrx;
708 unsigned int avail = (unsigned int)len;
709 uint8_t *buffer = *buf, mask[4];
710 #if !defined(LWS_WITHOUT_EXTENSIONS)
711 unsigned int old_packet_length = (int)wsi->ws->rx_packet_length;
716 * With zlib, we can give it as much input as we like. The pmd
717 * extension will draw it down in chunks (default 1024).
719 * If we try to restrict how much we give it, because we must go
720 * back to the event loop each time, we will drop the remainder...
723 #if !defined(LWS_WITHOUT_EXTENSIONS)
724 if (!wsi->ws->count_act_ext)
727 if (wsi->protocol->rx_buffer_size)
728 avail = (int)wsi->protocol->rx_buffer_size;
730 avail = wsi->context->pt_serv_buf_size;
733 /* do not consume more than we should */
734 if (avail > wsi->ws->rx_packet_length)
735 avail = (unsigned int)wsi->ws->rx_packet_length;
737 /* do not consume more than what is in the buffer */
739 avail = (unsigned int)len;
744 pmdrx.eb_in.token = buffer;
745 pmdrx.eb_in.len = avail;
746 pmdrx.eb_out.token = buffer;
747 pmdrx.eb_out.len = avail;
749 if (!wsi->ws->all_zero_nonce) {
751 for (n = 0; n < 4; n++)
752 mask[n] = wsi->ws->mask[(wsi->ws->mask_idx + n) & 3];
754 /* deal with 4-byte chunks using unwrapped loop */
757 *(buffer) = *(buffer) ^ mask[0];
759 *(buffer) = *(buffer) ^ mask[1];
761 *(buffer) = *(buffer) ^ mask[2];
763 *(buffer) = *(buffer) ^ mask[3];
766 /* and the remaining bytes bytewise */
767 for (n = 0; n < (int)(avail & 3); n++) {
768 *(buffer) = *(buffer) ^ mask[n];
772 wsi->ws->mask_idx = (wsi->ws->mask_idx + avail) & 3;
775 lwsl_info("%s: using %d of raw input (total %d on offer)\n", __func__,
780 wsi->ws->rx_packet_length -= avail;
782 #if !defined(LWS_WITHOUT_EXTENSIONS)
783 n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &pmdrx, 0);
784 lwsl_info("%s: ext says %d / ebuf_out.len %d\n", __func__, n,
788 * ebuf may be pointing somewhere completely different now,
794 * we may rely on this to get RX, just drop connection
796 lwsl_notice("%s: LWS_EXT_CB_PAYLOAD_RX blew out\n", __func__);
797 wsi->socket_is_permanently_unusable = 1;
803 * if we had an rx fragment right at the last compressed byte of the
804 * message, we can get a zero length inflated output, where no prior
805 * rx inflated output marked themselves with FIN, since there was
806 * raw ws payload still to drain at that time.
808 * Then we need to generate a zero length ws rx that can be understood
809 * as the message completion.
812 if (!pmdrx.eb_out.len && /* zero-length inflation output */
813 n == PMDR_EMPTY_FINAL && /* nothing to drain from the inflator */
814 old_packet_length && /* we gave the inflator new input */
815 !wsi->ws->rx_packet_length && /* raw ws packet payload all gone */
816 wsi->ws->final && /* the raw ws packet is a FIN guy */
817 wsi->protocol->callback &&
818 !wsi->wsistate_pre_close) {
820 lwsl_ext("%s: issuing zero length FIN pkt\n", __func__);
822 if (user_callback_handle_rxflow(wsi->protocol->callback, wsi,
823 LWS_CALLBACK_RECEIVE,
824 wsi->user_space, NULL, 0))
831 * If doing permessage-deflate, above was the only way to get a zero
832 * length receive. Otherwise we're more willing.
834 if (wsi->ws->count_act_ext && !pmdrx.eb_out.len)
837 if (n == PMDR_HAS_PENDING)
838 /* extension had more... main loop will come back */
839 lws_add_wsi_to_draining_ext_list(wsi);
841 lws_remove_wsi_from_draining_ext_list(wsi);
844 if (pmdrx.eb_out.len &&
845 wsi->ws->check_utf8 && !wsi->ws->defeat_check_utf8) {
846 if (lws_check_utf8(&wsi->ws->utf8,
849 lws_close_reason(wsi, LWS_CLOSE_STATUS_INVALID_PAYLOAD,
850 (uint8_t *)"bad utf8", 8);
854 /* we are ending partway through utf-8 character? */
855 if (!wsi->ws->rx_packet_length && wsi->ws->final &&
856 wsi->ws->utf8 && !n) {
857 lwsl_info("FINAL utf8 error\n");
858 lws_close_reason(wsi, LWS_CLOSE_STATUS_INVALID_PAYLOAD,
859 (uint8_t *)"partial utf8", 12);
862 lwsl_info("utf8 error\n");
863 lwsl_hexdump_info(pmdrx.eb_out.token, pmdrx.eb_out.len);
869 if (wsi->protocol->callback && !wsi->wsistate_pre_close)
870 if (user_callback_handle_rxflow(wsi->protocol->callback, wsi,
871 LWS_CALLBACK_RECEIVE,
877 wsi->ws->first_fragment = 0;
879 #if !defined(LWS_WITHOUT_EXTENSIONS)
880 lwsl_info("%s: input used %d, output %d, rem len %d, rx_draining_ext %d\n",
881 __func__, avail, pmdrx.eb_out.len, (int)len,
882 wsi->ws->rx_draining_ext);
885 return avail; /* how much we used from the input */
890 lws_parse_ws(struct lws *wsi, unsigned char **buf, size_t len)
892 unsigned char *bufin = *buf;
895 lwsl_debug("%s: received %d byte packet\n", __func__, (int)len);
897 //lwsl_hexdump_notice(*buf, len);
899 /* let the rx protocol state machine have as much as it needs */
903 * we were accepting input but now we stopped doing so
905 if (wsi->rxflow_bitmap) {
906 lwsl_info("%s: doing rxflow, caching %d\n", __func__,
909 * Since we cached the remaining available input, we
910 * can say we "consumed" it.
912 * But what about the case where the available input
913 * came out of the rxflow cache already? If we are
914 * effectively "putting it back in the cache", we have
915 * leave it where it is, already pointed to by the head.
917 if (lws_rxflow_cache(wsi, *buf, 0, (int)len) ==
920 * We dealt with it by trimming the existing
921 * rxflow cache HEAD to account for what we used.
923 * indicate we didn't use anything to the caller
924 * so he doesn't do any consumed processing
926 lwsl_info("%s: trimming inside rxflow cache\n",
934 #if !defined(LWS_WITHOUT_EXTENSIONS)
935 if (wsi->ws->rx_draining_ext) {
936 lwsl_debug("%s: draining rx ext\n", __func__);
937 m = lws_ws_rx_sm(wsi, ALREADY_PROCESSED_IGNORE_CHAR, 0);
944 /* consume payload bytes efficiently */
945 while (wsi->lws_rx_parse_state == LWS_RXPS_WS_FRAME_PAYLOAD &&
946 (wsi->ws->opcode == LWSWSOPC_TEXT_FRAME ||
947 wsi->ws->opcode == LWSWSOPC_BINARY_FRAME ||
948 wsi->ws->opcode == LWSWSOPC_CONTINUATION) &&
953 m = lws_ws_frame_rest_is_payload(wsi, buf, len);
954 assert((int)lws_ptr_diff(*buf, bin) <= (int)len);
955 len -= lws_ptr_diff(*buf, bin);
962 lwsl_info("%s: rest_is_payload bailed\n",
969 /* process the byte */
970 m = lws_ws_rx_sm(wsi, 0, *(*buf)++);
974 * We already handled this byte in bulk, just deal
975 * with the ramifications
977 #if !defined(LWS_WITHOUT_EXTENSIONS)
978 lwsl_debug("%s: coming out of bulk with len %d, "
979 "wsi->ws->rx_draining_ext %d\n",
981 wsi->ws->rx_draining_ext);
983 m = lws_ws_rx_sm(wsi, ALREADY_PROCESSED_IGNORE_CHAR |
984 ALREADY_PROCESSED_NO_CB, 0);
988 lwsl_info("%s: lws_ws_rx_sm bailed %d\n", __func__,
997 lwsl_debug("%s: exit with %d unused\n", __func__, (int)len);