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