2013-01-16 11:53:05 +08:00
|
|
|
/*
|
|
|
|
* libwebsockets - small server side websockets and web server implementation
|
|
|
|
*
|
2019-08-14 10:44:14 +01:00
|
|
|
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
2013-01-16 11:53:05 +08:00
|
|
|
*
|
2019-08-14 10:44:14 +01:00
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to
|
|
|
|
* deal in the Software without restriction, including without limitation the
|
|
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
2013-01-16 11:53:05 +08:00
|
|
|
*
|
2019-08-14 10:44:14 +01:00
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
2013-01-16 11:53:05 +08:00
|
|
|
*
|
2019-08-14 10:44:14 +01:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
* IN THE SOFTWARE.
|
2013-01-16 11:53:05 +08:00
|
|
|
*/
|
|
|
|
|
2019-08-15 10:49:52 +01:00
|
|
|
#include "private-lib-core.h"
|
2013-01-16 11:53:05 +08:00
|
|
|
|
2017-03-25 08:42:35 +08:00
|
|
|
/*
|
2018-04-11 13:39:42 +08:00
|
|
|
* parsers.c: lws_ws_rx_sm() needs to be roughly kept in
|
2017-03-25 08:42:35 +08:00
|
|
|
* sync with changes here, esp related to ext draining
|
|
|
|
*/
|
|
|
|
|
2018-04-20 10:33:23 +08:00
|
|
|
int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c)
|
2013-01-16 11:53:05 +08:00
|
|
|
{
|
|
|
|
int callback_action = LWS_CALLBACK_CLIENT_RECEIVE;
|
2019-05-04 13:19:12 +01:00
|
|
|
struct lws_ext_pm_deflate_rx_ebufs pmdrx;
|
2015-12-28 18:29:06 +08:00
|
|
|
unsigned short close_code;
|
2016-01-29 21:18:54 +08:00
|
|
|
unsigned char *pp;
|
2019-05-04 13:19:12 +01:00
|
|
|
int handled, m, n;
|
2018-05-03 10:49:36 +08:00
|
|
|
#if !defined(LWS_WITHOUT_EXTENSIONS)
|
2019-05-04 13:19:12 +01:00
|
|
|
int rx_draining_ext = 0;
|
2018-05-03 10:49:36 +08:00
|
|
|
#endif
|
2016-01-11 11:34:01 +08:00
|
|
|
|
2019-05-04 13:19:12 +01:00
|
|
|
pmdrx.eb_in.token = NULL;
|
|
|
|
pmdrx.eb_in.len = 0;
|
|
|
|
pmdrx.eb_out.token = NULL;
|
|
|
|
pmdrx.eb_out.len = 0;
|
2018-04-20 10:33:23 +08:00
|
|
|
|
2018-04-25 08:42:18 +08:00
|
|
|
#if !defined(LWS_WITHOUT_EXTENSIONS)
|
2017-12-01 11:09:32 +08:00
|
|
|
if (wsi->ws->rx_draining_ext) {
|
2016-01-11 11:34:01 +08:00
|
|
|
assert(!c);
|
2018-04-20 10:33:23 +08:00
|
|
|
|
2017-03-25 08:42:35 +08:00
|
|
|
lws_remove_wsi_from_draining_ext_list(wsi);
|
2016-01-11 11:34:01 +08:00
|
|
|
rx_draining_ext = 1;
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_debug(wsi, "doing draining flow");
|
2016-01-11 11:34:01 +08:00
|
|
|
|
|
|
|
goto drain_extension;
|
|
|
|
}
|
2018-04-25 08:42:18 +08:00
|
|
|
#endif
|
2013-01-16 11:53:05 +08:00
|
|
|
|
|
|
|
switch (wsi->lws_rx_parse_state) {
|
|
|
|
case LWS_RXPS_NEW:
|
2015-12-29 12:28:48 +08:00
|
|
|
/* control frames (PING) may interrupt checkable sequences */
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->defeat_check_utf8 = 0;
|
2013-01-16 11:53:05 +08:00
|
|
|
|
2017-12-01 11:09:32 +08:00
|
|
|
switch (wsi->ws->ietf_spec_revision) {
|
2013-01-21 09:53:35 +08:00
|
|
|
case 13:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->opcode = c & 0xf;
|
2015-12-28 14:12:10 +08:00
|
|
|
/* revisit if an extension wants them... */
|
2017-12-01 11:09:32 +08:00
|
|
|
switch (wsi->ws->opcode) {
|
2015-12-28 16:51:08 +08:00
|
|
|
case LWSWSOPC_TEXT_FRAME:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rsv_first_msg = (c & 0x70);
|
2019-05-04 13:19:12 +01:00
|
|
|
#if !defined(LWS_WITHOUT_EXTENSIONS)
|
|
|
|
/*
|
|
|
|
* set the expectation that we will have to
|
|
|
|
* fake up the zlib trailer to the inflator for
|
|
|
|
* this frame
|
|
|
|
*/
|
|
|
|
wsi->ws->pmd_trailer_application = !!(c & 0x40);
|
|
|
|
#endif
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->continuation_possible = 1;
|
|
|
|
wsi->ws->check_utf8 = lws_check_opt(
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
wsi->a.context->options,
|
2016-03-23 09:22:11 +08:00
|
|
|
LWS_SERVER_OPTION_VALIDATE_UTF8);
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->utf8 = 0;
|
2018-04-20 10:33:23 +08:00
|
|
|
wsi->ws->first_fragment = 1;
|
2015-12-28 16:51:08 +08:00
|
|
|
break;
|
2015-12-29 12:28:48 +08:00
|
|
|
case LWSWSOPC_BINARY_FRAME:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rsv_first_msg = (c & 0x70);
|
2019-05-04 13:19:12 +01:00
|
|
|
#if !defined(LWS_WITHOUT_EXTENSIONS)
|
|
|
|
/*
|
|
|
|
* set the expectation that we will have to
|
|
|
|
* fake up the zlib trailer to the inflator for
|
|
|
|
* this frame
|
|
|
|
*/
|
|
|
|
wsi->ws->pmd_trailer_application = !!(c & 0x40);
|
|
|
|
#endif
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->check_utf8 = 0;
|
|
|
|
wsi->ws->continuation_possible = 1;
|
2018-04-20 10:33:23 +08:00
|
|
|
wsi->ws->first_fragment = 1;
|
2015-12-29 12:28:48 +08:00
|
|
|
break;
|
2015-12-28 16:51:08 +08:00
|
|
|
case LWSWSOPC_CONTINUATION:
|
2017-12-01 11:09:32 +08:00
|
|
|
if (!wsi->ws->continuation_possible) {
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_info(wsi, "disordered continuation");
|
2015-12-28 16:51:08 +08:00
|
|
|
return -1;
|
|
|
|
}
|
2018-04-20 10:33:23 +08:00
|
|
|
wsi->ws->first_fragment = 0;
|
2015-12-28 16:51:08 +08:00
|
|
|
break;
|
2015-12-29 09:46:03 +08:00
|
|
|
case LWSWSOPC_CLOSE:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->check_utf8 = 0;
|
|
|
|
wsi->ws->utf8 = 0;
|
2015-12-29 09:46:03 +08:00
|
|
|
break;
|
2015-12-28 14:12:10 +08:00
|
|
|
case 3:
|
|
|
|
case 4:
|
|
|
|
case 5:
|
|
|
|
case 6:
|
|
|
|
case 7:
|
|
|
|
case 0xb:
|
|
|
|
case 0xc:
|
|
|
|
case 0xd:
|
|
|
|
case 0xe:
|
|
|
|
case 0xf:
|
2024-02-28 16:40:59 +08:00
|
|
|
if (wsi->ws->allow_unknown_opcode)
|
|
|
|
break;
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_info(wsi, "illegal opcode");
|
2015-12-28 14:12:10 +08:00
|
|
|
return -1;
|
|
|
|
default:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->defeat_check_utf8 = 1;
|
2015-12-28 14:12:10 +08:00
|
|
|
break;
|
|
|
|
}
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rsv = (c & 0x70);
|
2015-12-28 14:12:10 +08:00
|
|
|
/* revisit if an extension wants them... */
|
|
|
|
if (
|
2018-03-19 09:33:55 +08:00
|
|
|
#if !defined(LWS_WITHOUT_EXTENSIONS)
|
2018-04-25 06:53:30 +08:00
|
|
|
!wsi->ws->count_act_ext &&
|
2015-12-28 14:12:10 +08:00
|
|
|
#endif
|
2024-02-28 16:40:59 +08:00
|
|
|
wsi->ws->rsv && !wsi->ws->allow_reserved_bits) {
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_info(wsi, "illegal rsv bits set");
|
2015-12-28 14:12:10 +08:00
|
|
|
return -1;
|
|
|
|
}
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->final = !!((c >> 7) & 1);
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_ext(wsi, " This RX frame Final %d",
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->final);
|
2015-12-28 17:05:40 +08:00
|
|
|
|
2017-12-01 11:09:32 +08:00
|
|
|
if (wsi->ws->owed_a_fin &&
|
|
|
|
(wsi->ws->opcode == LWSWSOPC_TEXT_FRAME ||
|
|
|
|
wsi->ws->opcode == LWSWSOPC_BINARY_FRAME)) {
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_info(wsi, "hey you owed us a FIN");
|
2015-12-28 17:05:40 +08:00
|
|
|
return -1;
|
|
|
|
}
|
2017-12-01 11:09:32 +08:00
|
|
|
if ((!(wsi->ws->opcode & 8)) && wsi->ws->final) {
|
|
|
|
wsi->ws->continuation_possible = 0;
|
|
|
|
wsi->ws->owed_a_fin = 0;
|
2015-12-28 17:05:40 +08:00
|
|
|
}
|
2015-12-28 16:51:08 +08:00
|
|
|
|
2017-12-01 11:09:32 +08:00
|
|
|
if ((wsi->ws->opcode & 8) && !wsi->ws->final) {
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_info(wsi, "control msg can't be fragmented");
|
2015-12-28 14:12:10 +08:00
|
|
|
return -1;
|
|
|
|
}
|
2017-12-01 11:09:32 +08:00
|
|
|
if (!wsi->ws->final)
|
|
|
|
wsi->ws->owed_a_fin = 1;
|
2015-12-29 12:28:48 +08:00
|
|
|
|
2017-12-01 11:09:32 +08:00
|
|
|
switch (wsi->ws->opcode) {
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSWSOPC_TEXT_FRAME:
|
|
|
|
case LWSWSOPC_BINARY_FRAME:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->frame_is_binary = wsi->ws->opcode ==
|
2015-12-17 17:03:59 +08:00
|
|
|
LWSWSOPC_BINARY_FRAME;
|
2013-01-19 10:39:35 +08:00
|
|
|
break;
|
|
|
|
}
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_err(wsi, "unknown spec version %02d",
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->ietf_spec_revision);
|
2013-01-16 11:53:05 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_RXPS_04_FRAME_HDR_LEN:
|
|
|
|
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->this_frame_masked = !!(c & 0x80);
|
2021-11-10 16:26:18 +00:00
|
|
|
if (wsi->ws->this_frame_masked)
|
|
|
|
goto server_cannot_mask;
|
2013-01-16 11:53:05 +08:00
|
|
|
|
|
|
|
switch (c & 0x7f) {
|
|
|
|
case 126:
|
|
|
|
/* control frames are not allowed to have big lengths */
|
2017-12-01 11:09:32 +08:00
|
|
|
if (wsi->ws->opcode & 8)
|
2013-01-16 11:53:05 +08:00
|
|
|
goto illegal_ctl_length;
|
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
|
|
|
|
break;
|
|
|
|
case 127:
|
|
|
|
/* control frames are not allowed to have big lengths */
|
2017-12-01 11:09:32 +08:00
|
|
|
if (wsi->ws->opcode & 8)
|
2013-01-16 11:53:05 +08:00
|
|
|
goto illegal_ctl_length;
|
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
|
|
|
|
break;
|
|
|
|
default:
|
2018-04-20 10:33:23 +08:00
|
|
|
wsi->ws->rx_packet_length = c & 0x7f;
|
2017-12-01 11:09:32 +08:00
|
|
|
if (wsi->ws->this_frame_masked)
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state =
|
|
|
|
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
|
|
|
|
else {
|
2018-04-20 10:33:23 +08:00
|
|
|
if (wsi->ws->rx_packet_length) {
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state =
|
2018-04-20 10:33:23 +08:00
|
|
|
LWS_RXPS_WS_FRAME_PAYLOAD;
|
|
|
|
} else {
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
|
|
|
goto spill;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_RXPS_04_FRAME_HDR_LEN16_2:
|
2020-12-12 06:21:40 +00:00
|
|
|
wsi->ws->rx_packet_length = (size_t)((unsigned int)c << 8);
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_RXPS_04_FRAME_HDR_LEN16_1:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_packet_length |= c;
|
|
|
|
if (wsi->ws->this_frame_masked)
|
2016-01-29 21:18:54 +08:00
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_1;
|
2013-01-16 11:53:05 +08:00
|
|
|
else {
|
2017-12-01 11:09:32 +08:00
|
|
|
if (wsi->ws->rx_packet_length)
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state =
|
2018-04-20 10:33:23 +08:00
|
|
|
LWS_RXPS_WS_FRAME_PAYLOAD;
|
2013-01-16 11:53:05 +08:00
|
|
|
else {
|
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
|
|
|
goto spill;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_RXPS_04_FRAME_HDR_LEN64_8:
|
|
|
|
if (c & 0x80) {
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_warn(wsi, "b63 of length must be zero");
|
2013-01-16 11:53:05 +08:00
|
|
|
/* kill the connection */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#if defined __LP64__
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_packet_length = ((size_t)c) << 56;
|
2013-01-16 11:53:05 +08:00
|
|
|
#else
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_packet_length = 0;
|
2013-01-16 11:53:05 +08:00
|
|
|
#endif
|
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_RXPS_04_FRAME_HDR_LEN64_7:
|
|
|
|
#if defined __LP64__
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_packet_length |= ((size_t)c) << 48;
|
2013-01-16 11:53:05 +08:00
|
|
|
#endif
|
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_RXPS_04_FRAME_HDR_LEN64_6:
|
|
|
|
#if defined __LP64__
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_packet_length |= ((size_t)c) << 40;
|
2013-01-16 11:53:05 +08:00
|
|
|
#endif
|
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_RXPS_04_FRAME_HDR_LEN64_5:
|
|
|
|
#if defined __LP64__
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_packet_length |= ((size_t)c) << 32;
|
2013-01-16 11:53:05 +08:00
|
|
|
#endif
|
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_RXPS_04_FRAME_HDR_LEN64_4:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_packet_length |= ((size_t)c) << 24;
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_RXPS_04_FRAME_HDR_LEN64_3:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_packet_length |= ((size_t)c) << 16;
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_RXPS_04_FRAME_HDR_LEN64_2:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_packet_length |= ((size_t)c) << 8;
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_RXPS_04_FRAME_HDR_LEN64_1:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_packet_length |= (size_t)c;
|
|
|
|
if (wsi->ws->this_frame_masked)
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state =
|
|
|
|
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
|
|
|
|
else {
|
2017-12-01 11:09:32 +08:00
|
|
|
if (wsi->ws->rx_packet_length)
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state =
|
2018-04-20 10:33:23 +08:00
|
|
|
LWS_RXPS_WS_FRAME_PAYLOAD;
|
2013-01-16 11:53:05 +08:00
|
|
|
else {
|
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
|
|
|
goto spill;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->mask[0] = c;
|
2013-01-16 11:53:05 +08:00
|
|
|
if (c)
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->all_zero_nonce = 0;
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->mask[1] = c;
|
2013-01-16 11:53:05 +08:00
|
|
|
if (c)
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->all_zero_nonce = 0;
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->mask[2] = c;
|
2013-01-16 11:53:05 +08:00
|
|
|
if (c)
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->all_zero_nonce = 0;
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->mask[3] = c;
|
2013-01-16 11:53:05 +08:00
|
|
|
if (c)
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->all_zero_nonce = 0;
|
2013-01-16 11:53:05 +08:00
|
|
|
|
2017-12-01 11:09:32 +08:00
|
|
|
if (wsi->ws->rx_packet_length)
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state =
|
2018-04-20 10:33:23 +08:00
|
|
|
LWS_RXPS_WS_FRAME_PAYLOAD;
|
2013-01-16 11:53:05 +08:00
|
|
|
else {
|
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
|
|
|
goto spill;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2018-04-20 10:33:23 +08:00
|
|
|
case LWS_RXPS_WS_FRAME_PAYLOAD:
|
2013-02-06 21:10:16 +09:00
|
|
|
|
2017-12-01 11:09:32 +08:00
|
|
|
assert(wsi->ws->rx_ubuf);
|
2018-04-25 08:42:18 +08:00
|
|
|
#if !defined(LWS_WITHOUT_EXTENSIONS)
|
2017-12-01 11:09:32 +08:00
|
|
|
if (wsi->ws->rx_draining_ext)
|
2017-03-25 08:42:35 +08:00
|
|
|
goto drain_extension;
|
2018-04-25 08:42:18 +08:00
|
|
|
#endif
|
2017-12-01 11:09:32 +08:00
|
|
|
if (wsi->ws->this_frame_masked && !wsi->ws->all_zero_nonce)
|
|
|
|
c ^= wsi->ws->mask[(wsi->ws->mask_idx++) & 3];
|
2013-01-16 11:53:05 +08:00
|
|
|
|
2019-05-04 13:19:12 +01:00
|
|
|
/*
|
|
|
|
* unmask and collect the payload body in
|
|
|
|
* rx_ubuf_head + LWS_PRE
|
|
|
|
*/
|
|
|
|
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_ubuf[LWS_PRE + (wsi->ws->rx_ubuf_head++)] = c;
|
2015-12-29 09:46:03 +08:00
|
|
|
|
2017-12-01 11:09:32 +08:00
|
|
|
if (--wsi->ws->rx_packet_length == 0) {
|
2013-02-14 10:18:31 +08:00
|
|
|
/* spill because we have the whole frame */
|
2013-01-16 11:53:05 +08:00
|
|
|
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_debug(wsi, "spilling as we have the whole frame");
|
2013-01-16 11:53:05 +08:00
|
|
|
goto spill;
|
|
|
|
}
|
2013-02-14 10:18:31 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* if there's no protocol max frame size given, we are
|
2016-05-19 12:34:35 +08:00
|
|
|
* supposed to default to context->pt_serv_buf_size
|
2013-02-14 10:18:31 +08:00
|
|
|
*/
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
if (!wsi->a.protocol->rx_buffer_size &&
|
|
|
|
wsi->ws->rx_ubuf_head != wsi->a.context->pt_serv_buf_size)
|
2013-01-16 11:53:05 +08:00
|
|
|
break;
|
2015-12-29 12:28:48 +08:00
|
|
|
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
if (wsi->a.protocol->rx_buffer_size &&
|
|
|
|
wsi->ws->rx_ubuf_head != wsi->a.protocol->rx_buffer_size)
|
2013-02-14 10:18:31 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* spill because we filled our rx buffer */
|
2019-05-04 13:19:12 +01:00
|
|
|
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_debug(wsi, "spilling as we filled our rx buffer");
|
2013-01-16 11:53:05 +08:00
|
|
|
spill:
|
|
|
|
|
|
|
|
handled = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* is this frame a control packet we should take care of at this
|
|
|
|
* layer? If so service it and hide it from the user callback
|
|
|
|
*/
|
|
|
|
|
2017-12-01 11:09:32 +08:00
|
|
|
switch (wsi->ws->opcode) {
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSWSOPC_CLOSE:
|
2019-05-30 08:21:33 +08:00
|
|
|
pp = &wsi->ws->rx_ubuf[LWS_PRE];
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
if (lws_check_opt(wsi->a.context->options,
|
2016-03-23 09:22:11 +08:00
|
|
|
LWS_SERVER_OPTION_VALIDATE_UTF8) &&
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_ubuf_head > 2 &&
|
|
|
|
lws_check_utf8(&wsi->ws->utf8, pp + 2,
|
|
|
|
wsi->ws->rx_ubuf_head - 2))
|
2015-12-30 11:43:36 +08:00
|
|
|
goto utf8_fail;
|
|
|
|
|
2018-04-02 11:55:17 +08:00
|
|
|
/* is this an acknowledgment of our close? */
|
|
|
|
if (lwsi_state(wsi) == LRS_AWAITING_CLOSE_ACK) {
|
2013-01-16 11:53:05 +08:00
|
|
|
/*
|
|
|
|
* fine he has told us he is closing too, let's
|
|
|
|
* finish our close
|
|
|
|
*/
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_parser(wsi, "seen server's close ack");
|
2013-01-16 11:53:05 +08:00
|
|
|
return -1;
|
|
|
|
}
|
2015-12-30 11:43:36 +08:00
|
|
|
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_parser(wsi, "client sees server close len = %d",
|
2020-01-16 07:16:01 +00:00
|
|
|
(int)wsi->ws->rx_ubuf_head);
|
2017-12-01 11:09:32 +08:00
|
|
|
if (wsi->ws->rx_ubuf_head >= 2) {
|
2020-12-12 06:21:40 +00:00
|
|
|
close_code = (unsigned short)((pp[0] << 8) | pp[1]);
|
2017-03-25 08:42:35 +08:00
|
|
|
if (close_code < 1000 ||
|
|
|
|
close_code == 1004 ||
|
|
|
|
close_code == 1005 ||
|
|
|
|
close_code == 1006 ||
|
2015-12-28 18:29:06 +08:00
|
|
|
(close_code >= 1016 && close_code < 3000)
|
|
|
|
) {
|
|
|
|
pp[0] = (LWS_CLOSE_STATUS_PROTOCOL_ERR >> 8) & 0xff;
|
|
|
|
pp[1] = LWS_CLOSE_STATUS_PROTOCOL_ERR & 0xff;
|
|
|
|
}
|
|
|
|
}
|
2015-12-26 17:20:34 +08:00
|
|
|
if (user_callback_handle_rxflow(
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
wsi->a.protocol->callback, wsi,
|
2015-12-26 17:20:34 +08:00
|
|
|
LWS_CALLBACK_WS_PEER_INITIATED_CLOSE,
|
2015-12-28 18:29:06 +08:00
|
|
|
wsi->user_space, pp,
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_ubuf_head))
|
2015-12-26 17:20:34 +08:00
|
|
|
return -1;
|
2017-03-25 08:42:35 +08:00
|
|
|
|
2018-04-20 10:33:23 +08:00
|
|
|
memcpy(wsi->ws->ping_payload_buf + LWS_PRE, pp,
|
|
|
|
wsi->ws->rx_ubuf_head);
|
2018-11-23 08:47:56 +08:00
|
|
|
wsi->ws->close_in_ping_buffer_len =
|
2020-12-12 06:21:40 +00:00
|
|
|
(uint8_t)wsi->ws->rx_ubuf_head;
|
2018-04-20 10:33:23 +08:00
|
|
|
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_info(wsi, "scheduling return close as ack");
|
2018-04-20 10:33:23 +08:00
|
|
|
__lws_change_pollfd(wsi, LWS_POLLIN, 0);
|
|
|
|
lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_SEND, 3);
|
|
|
|
wsi->waiting_to_send_close_frame = 1;
|
|
|
|
wsi->close_needs_ack = 0;
|
|
|
|
lwsi_set_state(wsi, LRS_WAITING_TO_SEND_CLOSE);
|
|
|
|
lws_callback_on_writable(wsi);
|
|
|
|
handled = 1;
|
|
|
|
break;
|
2013-01-16 11:53:05 +08:00
|
|
|
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSWSOPC_PING:
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_info(wsi, "received %d byte ping, sending pong",
|
2020-01-16 07:16:01 +00:00
|
|
|
(int)wsi->ws->rx_ubuf_head);
|
2015-03-24 21:22:52 +08:00
|
|
|
|
2015-12-26 17:20:34 +08:00
|
|
|
/* he set a close reason on this guy, ignore PING */
|
2017-12-01 11:09:32 +08:00
|
|
|
if (wsi->ws->close_in_ping_buffer_len)
|
2015-12-26 17:20:34 +08:00
|
|
|
goto ping_drop;
|
|
|
|
|
2021-09-13 17:57:08 +03:00
|
|
|
if (wsi->ws->pong_pending_flag) {
|
2015-03-24 21:22:52 +08:00
|
|
|
/*
|
2021-09-13 17:57:08 +03:00
|
|
|
* there is already a pending pong payload
|
2015-03-24 21:22:52 +08:00
|
|
|
* we should just log and drop
|
|
|
|
*/
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_parser(wsi, "DROP PING since one pending");
|
2015-03-24 21:22:52 +08:00
|
|
|
goto ping_drop;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* control packets can only be < 128 bytes long */
|
2017-12-01 11:09:32 +08:00
|
|
|
if (wsi->ws->rx_ubuf_head > 128 - 3) {
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_parser(wsi, "DROP PING payload too large");
|
2015-03-24 21:22:52 +08:00
|
|
|
goto ping_drop;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* stash the pong payload */
|
2021-09-13 17:57:08 +03:00
|
|
|
memcpy(wsi->ws->pong_payload_buf + LWS_PRE,
|
2017-12-01 11:09:32 +08:00
|
|
|
&wsi->ws->rx_ubuf[LWS_PRE],
|
2018-11-23 08:47:56 +08:00
|
|
|
wsi->ws->rx_ubuf_head);
|
2015-03-24 21:22:52 +08:00
|
|
|
|
2021-09-13 17:57:08 +03:00
|
|
|
wsi->ws->pong_payload_len = (uint8_t)wsi->ws->rx_ubuf_head;
|
|
|
|
wsi->ws->pong_pending_flag = 1;
|
2015-03-24 21:22:52 +08:00
|
|
|
|
|
|
|
/* get it sent as soon as possible */
|
2015-12-16 18:19:08 +08:00
|
|
|
lws_callback_on_writable(wsi);
|
2015-03-24 21:22:52 +08:00
|
|
|
ping_drop:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_ubuf_head = 0;
|
2013-01-16 11:53:05 +08:00
|
|
|
handled = 1;
|
|
|
|
break;
|
|
|
|
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSWSOPC_PONG:
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_info(wsi, "Received pong");
|
|
|
|
lwsl_hexdump_wsi_debug(wsi, &wsi->ws->rx_ubuf[LWS_PRE],
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_ubuf_head);
|
2013-01-16 11:53:05 +08:00
|
|
|
|
2019-09-18 13:09:32 +01:00
|
|
|
lws_validity_confirmed(wsi);
|
2013-01-16 11:53:05 +08:00
|
|
|
/* issue it */
|
|
|
|
callback_action = LWS_CALLBACK_CLIENT_RECEIVE_PONG;
|
|
|
|
break;
|
|
|
|
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSWSOPC_CONTINUATION:
|
|
|
|
case LWSWSOPC_TEXT_FRAME:
|
|
|
|
case LWSWSOPC_BINARY_FRAME:
|
2013-01-16 11:53:05 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2018-04-20 10:33:23 +08:00
|
|
|
/* not handled or failed */
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_ext(wsi, "Unhandled ext opc 0x%x", wsi->ws->opcode);
|
2018-04-20 10:33:23 +08:00
|
|
|
wsi->ws->rx_ubuf_head = 0;
|
2013-01-16 11:53:05 +08:00
|
|
|
|
2018-04-20 10:33:23 +08:00
|
|
|
return -1;
|
2013-01-16 11:53:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No it's real payload, pass it up to the user callback.
|
2019-05-04 13:19:12 +01:00
|
|
|
*
|
|
|
|
* We have been statefully collecting it in the
|
|
|
|
* LWS_RXPS_WS_FRAME_PAYLOAD clause above.
|
|
|
|
*
|
2013-01-16 11:53:05 +08:00
|
|
|
* It's nicely buffered with the pre-padding taken care of
|
2019-05-04 13:19:12 +01:00
|
|
|
* so it can be sent straight out again using lws_write.
|
|
|
|
*
|
|
|
|
* However, now we have a chunk of it, we want to deal with it
|
|
|
|
* all here. Since this may be input to permessage-deflate and
|
|
|
|
* there are block limits on that for input and output, we may
|
|
|
|
* need to iterate.
|
2013-01-16 11:53:05 +08:00
|
|
|
*/
|
|
|
|
if (handled)
|
|
|
|
goto already_done;
|
|
|
|
|
2019-05-04 13:19:12 +01:00
|
|
|
pmdrx.eb_in.token = &wsi->ws->rx_ubuf[LWS_PRE];
|
2020-12-12 06:21:40 +00:00
|
|
|
pmdrx.eb_in.len = (int)wsi->ws->rx_ubuf_head;
|
2019-05-04 13:19:12 +01:00
|
|
|
|
|
|
|
/* for the non-pm-deflate case */
|
|
|
|
|
|
|
|
pmdrx.eb_out = pmdrx.eb_in;
|
|
|
|
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_debug(wsi, "starting disbursal of %d deframed rx",
|
|
|
|
(int)wsi->ws->rx_ubuf_head);
|
2015-12-14 08:52:03 +08:00
|
|
|
|
2018-03-19 19:22:41 +08:00
|
|
|
#if !defined(LWS_WITHOUT_EXTENSIONS)
|
2018-04-25 08:42:18 +08:00
|
|
|
drain_extension:
|
2018-03-19 19:22:41 +08:00
|
|
|
#endif
|
2019-05-04 13:19:12 +01:00
|
|
|
do {
|
|
|
|
|
2021-10-13 01:47:40 -04:00
|
|
|
// lwsl_wsi_notice("pmdrx.eb_in.len: %d",
|
2019-05-04 13:19:12 +01:00
|
|
|
// (int)pmdrx.eb_in.len);
|
|
|
|
|
|
|
|
n = PMDR_DID_NOTHING;
|
2016-01-11 11:34:01 +08:00
|
|
|
|
2018-05-03 10:49:36 +08:00
|
|
|
#if !defined(LWS_WITHOUT_EXTENSIONS)
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_ext(wsi, "+++ passing %d %p to ext",
|
2019-05-04 13:19:12 +01:00
|
|
|
pmdrx.eb_in.len, pmdrx.eb_in.token);
|
|
|
|
|
|
|
|
n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX,
|
|
|
|
&pmdrx, 0);
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_ext(wsi, "Ext RX returned %d", n);
|
2019-05-04 13:19:12 +01:00
|
|
|
if (n < 0) {
|
|
|
|
wsi->socket_is_permanently_unusable = 1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (n == PMDR_DID_NOTHING)
|
2020-10-08 14:06:43 +01:00
|
|
|
/* ie, not PMDR_NOTHING_WE_SHOULD_DO */
|
2019-05-04 13:19:12 +01:00
|
|
|
break;
|
2018-05-09 18:06:45 +08:00
|
|
|
#endif
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_ext(wsi, "post inflate ebuf in len %d / out len %d",
|
|
|
|
pmdrx.eb_in.len, pmdrx.eb_out.len);
|
2016-01-11 11:34:01 +08:00
|
|
|
|
2019-05-04 13:19:12 +01:00
|
|
|
#if !defined(LWS_WITHOUT_EXTENSIONS)
|
|
|
|
if (rx_draining_ext && !pmdrx.eb_out.len) {
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_debug(wsi, " --- ending drain on 0 read result");
|
2019-05-04 13:19:12 +01:00
|
|
|
goto already_done;
|
2018-04-20 10:33:23 +08:00
|
|
|
}
|
2015-12-30 11:43:36 +08:00
|
|
|
|
2019-05-04 13:19:12 +01:00
|
|
|
if (n == PMDR_HAS_PENDING) { /* 1 means stuff to drain */
|
|
|
|
/* extension had more... main loop will come back */
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_ext(wsi, "adding to draining ext list");
|
2019-05-04 13:19:12 +01:00
|
|
|
lws_add_wsi_to_draining_ext_list(wsi);
|
|
|
|
} else {
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_ext(wsi, "removing from draining ext list");
|
2019-05-04 13:19:12 +01:00
|
|
|
lws_remove_wsi_from_draining_ext_list(wsi);
|
|
|
|
}
|
|
|
|
rx_draining_ext = wsi->ws->rx_draining_ext;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (wsi->ws->check_utf8 && !wsi->ws->defeat_check_utf8) {
|
|
|
|
|
|
|
|
if (lws_check_utf8(&wsi->ws->utf8,
|
2019-05-30 08:21:33 +08:00
|
|
|
pmdrx.eb_out.token,
|
2020-12-12 06:21:40 +00:00
|
|
|
(unsigned int)pmdrx.eb_out.len)) {
|
2019-05-04 13:19:12 +01:00
|
|
|
lws_close_reason(wsi,
|
|
|
|
LWS_CLOSE_STATUS_INVALID_PAYLOAD,
|
|
|
|
(uint8_t *)"bad utf8", 8);
|
|
|
|
goto utf8_fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we are ending partway through utf-8 character? */
|
|
|
|
if (!wsi->ws->rx_packet_length &&
|
|
|
|
wsi->ws->final && wsi->ws->utf8
|
2018-05-03 10:49:36 +08:00
|
|
|
#if !defined(LWS_WITHOUT_EXTENSIONS)
|
2019-05-04 13:19:12 +01:00
|
|
|
/* if ext not negotiated, going to be UNKNOWN */
|
|
|
|
&& (n == PMDR_EMPTY_FINAL || n == PMDR_UNKNOWN)
|
2018-05-03 10:49:36 +08:00
|
|
|
#endif
|
2019-05-04 13:19:12 +01:00
|
|
|
) {
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_info(wsi, "FINAL utf8 error");
|
2019-05-04 13:19:12 +01:00
|
|
|
lws_close_reason(wsi,
|
|
|
|
LWS_CLOSE_STATUS_INVALID_PAYLOAD,
|
|
|
|
(uint8_t *)"partial utf8", 12);
|
2017-09-23 12:55:21 +08:00
|
|
|
utf8_fail:
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_info(wsi, "utf8 error");
|
|
|
|
lwsl_hexdump_wsi_info(wsi, pmdrx.eb_out.token,
|
2020-12-12 06:21:40 +00:00
|
|
|
(unsigned int)pmdrx.eb_out.len);
|
2018-04-20 10:33:23 +08:00
|
|
|
|
2019-05-04 13:19:12 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2015-12-30 11:43:36 +08:00
|
|
|
}
|
|
|
|
|
2019-05-04 13:19:12 +01:00
|
|
|
if (pmdrx.eb_out.len < 0 &&
|
|
|
|
callback_action != LWS_CALLBACK_CLIENT_RECEIVE_PONG)
|
|
|
|
goto already_done;
|
2013-02-11 17:13:32 +08:00
|
|
|
|
2019-05-04 13:19:12 +01:00
|
|
|
if (!pmdrx.eb_out.token)
|
|
|
|
goto already_done;
|
2016-01-11 11:34:01 +08:00
|
|
|
|
2019-05-04 13:19:12 +01:00
|
|
|
pmdrx.eb_out.token[pmdrx.eb_out.len] = '\0';
|
2013-02-11 17:13:32 +08:00
|
|
|
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
if (!wsi->a.protocol->callback)
|
2019-05-04 13:19:12 +01:00
|
|
|
goto already_done;
|
2013-02-11 17:13:32 +08:00
|
|
|
|
2019-05-04 13:19:12 +01:00
|
|
|
if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG)
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_info(wsi, "Client doing pong callback");
|
2013-02-11 17:13:32 +08:00
|
|
|
|
2018-05-03 10:49:36 +08:00
|
|
|
#if !defined(LWS_WITHOUT_EXTENSIONS)
|
2019-05-04 13:19:12 +01:00
|
|
|
if (n == PMDR_HAS_PENDING)
|
|
|
|
/* extension had more... main loop will come back
|
|
|
|
* we want callback to be done with this set, if so,
|
|
|
|
* because lws_is_final() hides it was final until the
|
|
|
|
* last chunk
|
|
|
|
*/
|
|
|
|
lws_add_wsi_to_draining_ext_list(wsi);
|
|
|
|
else
|
|
|
|
lws_remove_wsi_from_draining_ext_list(wsi);
|
2018-05-03 10:49:36 +08:00
|
|
|
#endif
|
2016-01-11 11:34:01 +08:00
|
|
|
|
2019-05-04 13:19:12 +01:00
|
|
|
if (lwsi_state(wsi) == LRS_RETURNED_CLOSE ||
|
|
|
|
lwsi_state(wsi) == LRS_WAITING_TO_SEND_CLOSE ||
|
|
|
|
lwsi_state(wsi) == LRS_AWAITING_CLOSE_ACK)
|
|
|
|
goto already_done;
|
2013-02-11 17:13:32 +08:00
|
|
|
|
2019-05-04 13:19:12 +01:00
|
|
|
/* if pmd not enabled, in == out */
|
2018-04-20 10:33:23 +08:00
|
|
|
|
2019-06-08 10:29:08 +01:00
|
|
|
if (n == PMDR_DID_NOTHING
|
|
|
|
#if !defined(LWS_WITHOUT_EXTENSIONS)
|
2023-04-24 14:23:49 +08:00
|
|
|
|| n == PMDR_NOTHING_WE_SHOULD_DO
|
2019-06-08 10:29:08 +01:00
|
|
|
|| n == PMDR_UNKNOWN
|
|
|
|
#endif
|
|
|
|
)
|
2019-05-04 13:19:12 +01:00
|
|
|
pmdrx.eb_in.len -= pmdrx.eb_out.len;
|
2018-04-20 10:33:23 +08:00
|
|
|
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
m = wsi->a.protocol->callback(wsi,
|
2019-05-04 13:19:12 +01:00
|
|
|
(enum lws_callback_reasons)callback_action,
|
|
|
|
wsi->user_space, pmdrx.eb_out.token,
|
2020-12-12 06:21:40 +00:00
|
|
|
(unsigned int)pmdrx.eb_out.len);
|
2019-05-04 13:19:12 +01:00
|
|
|
|
|
|
|
wsi->ws->first_fragment = 0;
|
|
|
|
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_debug(wsi, "bulk ws rx: inp used %d, output %d",
|
|
|
|
(int)wsi->ws->rx_ubuf_head,
|
2020-01-16 07:16:01 +00:00
|
|
|
(int)pmdrx.eb_out.len);
|
2019-05-04 13:19:12 +01:00
|
|
|
|
|
|
|
/* if user code wants to close, let caller know */
|
|
|
|
if (m)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
} while (pmdrx.eb_in.len
|
|
|
|
#if !defined(LWS_WITHOUT_EXTENSIONS)
|
|
|
|
|| rx_draining_ext
|
|
|
|
#endif
|
|
|
|
);
|
2014-03-15 09:32:40 +08:00
|
|
|
|
2013-01-16 11:53:05 +08:00
|
|
|
already_done:
|
2017-12-01 11:09:32 +08:00
|
|
|
wsi->ws->rx_ubuf_head = 0;
|
2013-01-16 11:53:05 +08:00
|
|
|
break;
|
|
|
|
default:
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_err(wsi, "client rx illegal state");
|
2013-01-16 11:53:05 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
illegal_ctl_length:
|
2021-10-13 01:47:40 -04:00
|
|
|
lwsl_wsi_warn(wsi, "Control frame asking for extended length is illegal");
|
2017-09-23 12:55:21 +08:00
|
|
|
|
2021-11-10 16:26:18 +00:00
|
|
|
/* kill the connection */
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
server_cannot_mask:
|
|
|
|
lws_close_reason(wsi,
|
|
|
|
LWS_CLOSE_STATUS_PROTOCOL_ERR,
|
|
|
|
(uint8_t *)"srv mask", 8);
|
|
|
|
|
|
|
|
lwsl_wsi_warn(wsi, "Server must not mask");
|
|
|
|
|
2013-01-16 11:53:05 +08:00
|
|
|
/* kill the connection */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|