2019-01-13 06:58:21 +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>
|
2019-01-13 06:58:21 +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:
|
2019-01-13 06:58:21 +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.
|
2019-01-13 06:58:21 +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.
|
2019-01-13 06:58:21 +08:00
|
|
|
*/
|
|
|
|
|
2019-08-15 10:49:52 +01:00
|
|
|
#include "private-lib-core.h"
|
2019-01-13 06:58:21 +08:00
|
|
|
|
2020-12-25 05:54:19 +00:00
|
|
|
const char *
|
|
|
|
lws_wsi_tag(struct lws *wsi)
|
|
|
|
{
|
2020-12-27 16:05:48 +00:00
|
|
|
if (!wsi)
|
|
|
|
return "[null wsi]";
|
2020-12-25 05:54:19 +00:00
|
|
|
return lws_lc_tag(&wsi->lc);
|
|
|
|
}
|
|
|
|
|
2019-01-13 06:58:21 +08:00
|
|
|
#if defined (_DEBUG)
|
|
|
|
void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role)
|
|
|
|
{
|
|
|
|
wsi->wsistate = (wsi->wsistate & (~LWSI_ROLE_MASK)) | role;
|
|
|
|
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_debug(wsi, "state 0x%lx", (unsigned long)wsi->wsistate);
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs)
|
|
|
|
{
|
2021-06-17 10:07:04 +01:00
|
|
|
lws_wsi_state_t old = wsi->wsistate;
|
2019-01-13 06:58:21 +08:00
|
|
|
|
2021-06-17 10:07:04 +01:00
|
|
|
wsi->wsistate = (old & (unsigned int)(~LRS_MASK)) | lrs;
|
|
|
|
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_debug(wsi, "lwsi_set_state 0x%lx -> 0x%lx",
|
2021-06-17 10:07:04 +01:00
|
|
|
(unsigned long)old, (unsigned long)wsi->wsistate);
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2021-06-26 17:24:19 +01:00
|
|
|
void
|
|
|
|
lws_log_prepend_wsi(struct lws_log_cx *cx, void *obj, char **p, char *e)
|
|
|
|
{
|
|
|
|
struct lws *wsi = (struct lws *)obj;
|
|
|
|
|
|
|
|
*p += lws_snprintf(*p, lws_ptr_diff_size_t(e, (*p)), "%s: ",
|
|
|
|
lws_wsi_tag(wsi));
|
|
|
|
}
|
|
|
|
|
2019-01-13 06:58:21 +08:00
|
|
|
void
|
|
|
|
lws_vhost_bind_wsi(struct lws_vhost *vh, struct lws *wsi)
|
|
|
|
{
|
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.vhost == vh)
|
2019-01-13 06:58:21 +08:00
|
|
|
return;
|
2021-06-17 10:07:04 +01:00
|
|
|
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_context_lock(vh->context, __func__); /* ---------- context { */
|
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.vhost = vh;
|
2021-05-21 14:32:21 +01:00
|
|
|
|
|
|
|
#if defined(LWS_WITH_TLS_JIT_TRUST)
|
|
|
|
if (!vh->count_bound_wsi && vh->grace_after_unref) {
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_info(wsi, "in use");
|
2021-05-21 14:32:21 +01:00
|
|
|
lws_sul_cancel(&vh->sul_unref);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-01-13 06:58:21 +08:00
|
|
|
vh->count_bound_wsi++;
|
|
|
|
lws_context_unlock(vh->context); /* } context ---------- */
|
2021-06-17 10:07:04 +01:00
|
|
|
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_debug(wsi, "vh %s: wsi %s/%s, count_bound_wsi %d\n",
|
2020-02-25 13:28:25 +00:00
|
|
|
vh->name, wsi->role_ops ? wsi->role_ops->name : "none",
|
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 ? wsi->a.protocol->name : "none",
|
2020-02-25 13:28:25 +00:00
|
|
|
vh->count_bound_wsi);
|
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
|
|
|
assert(wsi->a.vhost->count_bound_wsi > 0);
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
2021-04-04 04:06:24 +01:00
|
|
|
|
|
|
|
/* req cx lock... acquires vh lock */
|
2019-01-13 06:58:21 +08:00
|
|
|
void
|
2021-04-04 04:06:24 +01:00
|
|
|
__lws_vhost_unbind_wsi(struct lws *wsi)
|
2019-01-13 06:58:21 +08:00
|
|
|
{
|
2021-05-21 14:32:21 +01:00
|
|
|
struct lws_vhost *vh = wsi->a.vhost;
|
|
|
|
|
|
|
|
if (!vh)
|
|
|
|
return;
|
2019-01-13 06:58:21 +08:00
|
|
|
|
2021-04-04 04:06:24 +01:00
|
|
|
lws_context_assert_lock_held(wsi->a.context);
|
|
|
|
|
2021-05-21 14:32:21 +01:00
|
|
|
lws_vhost_lock(vh);
|
|
|
|
|
|
|
|
assert(vh->count_bound_wsi > 0);
|
|
|
|
vh->count_bound_wsi--;
|
|
|
|
|
|
|
|
#if defined(LWS_WITH_TLS_JIT_TRUST)
|
|
|
|
if (!vh->count_bound_wsi && vh->grace_after_unref)
|
|
|
|
lws_tls_jit_trust_vh_start_grace(vh);
|
|
|
|
#endif
|
2019-01-13 06:58:21 +08:00
|
|
|
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_debug(wsi, "vh %s: count_bound_wsi %d",
|
2021-05-21 14:32:21 +01:00
|
|
|
vh->name, vh->count_bound_wsi);
|
2019-01-13 06:58:21 +08:00
|
|
|
|
2021-05-21 14:32:21 +01:00
|
|
|
lws_vhost_unlock(vh);
|
|
|
|
|
|
|
|
if (!vh->count_bound_wsi && vh->being_destroyed)
|
2019-01-13 06:58:21 +08:00
|
|
|
/*
|
|
|
|
* We have closed all wsi that were bound to this vhost
|
|
|
|
* by any pt: nothing can be servicing any wsi belonging
|
|
|
|
* to it any more.
|
|
|
|
*
|
2021-04-04 04:06:24 +01:00
|
|
|
* Finalize the vh destruction... must drop vh lock
|
2019-01-13 06:58:21 +08:00
|
|
|
*/
|
2021-05-21 14:32:21 +01:00
|
|
|
__lws_vhost_destroy2(vh);
|
2019-01-13 06:58:21 +08:00
|
|
|
|
2021-04-04 04:06:24 +01:00
|
|
|
wsi->a.vhost = NULL;
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
struct lws *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_network_wsi(struct lws *wsi)
|
|
|
|
{
|
|
|
|
if (!wsi)
|
|
|
|
return NULL;
|
|
|
|
|
2020-02-25 13:28:25 +00:00
|
|
|
#if defined(LWS_WITH_HTTP2) || defined(LWS_ROLE_MQTT)
|
2019-12-23 11:31:57 +00:00
|
|
|
if (!wsi->mux_substream
|
2019-08-18 05:04:15 +01:00
|
|
|
#if defined(LWS_WITH_CLIENT)
|
2019-12-23 11:31:57 +00:00
|
|
|
&& !wsi->client_mux_substream
|
2019-01-13 06:58:21 +08:00
|
|
|
#endif
|
|
|
|
)
|
|
|
|
return wsi;
|
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
while (wsi->mux.parent_wsi)
|
|
|
|
wsi = wsi->mux.parent_wsi;
|
2019-01-13 06:58:21 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return wsi;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
const struct lws_protocols *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_vhost_name_to_protocol(struct lws_vhost *vh, const char *name)
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
|
|
|
|
for (n = 0; n < vh->count_protocols; n++)
|
2019-03-17 10:03:22 +08:00
|
|
|
if (vh->protocols[n].name && !strcmp(name, vh->protocols[n].name))
|
2019-01-13 06:58:21 +08:00
|
|
|
return &vh->protocols[n];
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_callback_all_protocol(struct lws_context *context,
|
|
|
|
const struct lws_protocols *protocol, int reason)
|
|
|
|
{
|
|
|
|
struct lws_context_per_thread *pt = &context->pt[0];
|
|
|
|
unsigned int n, m = context->count_threads;
|
|
|
|
struct lws *wsi;
|
|
|
|
|
|
|
|
while (m--) {
|
|
|
|
for (n = 0; n < pt->fds_count; n++) {
|
|
|
|
wsi = wsi_from_fd(context, pt->fds[n].fd);
|
2024-03-26 22:15:45 +01:00
|
|
|
if (!wsi || !wsi->a.protocol)
|
2019-01-13 06:58:21 +08:00
|
|
|
continue;
|
2024-03-26 22:15:45 +01:00
|
|
|
if (wsi->a.protocol->callback == protocol->callback &&
|
|
|
|
!strcmp(protocol->name, wsi->a.protocol->name))
|
2020-12-12 06:21:40 +00:00
|
|
|
protocol->callback(wsi,
|
|
|
|
(enum lws_callback_reasons)reason,
|
|
|
|
wsi->user_space, NULL, 0);
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
pt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-06-06 07:22:28 +01:00
|
|
|
void *
|
|
|
|
lws_evlib_wsi_to_evlib_pt(struct lws *wsi)
|
|
|
|
{
|
|
|
|
struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
|
|
|
|
|
|
|
|
return pt->evlib_pt;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
lws_evlib_tsi_to_evlib_pt(struct lws_context *cx, int tsi)
|
|
|
|
{
|
|
|
|
struct lws_context_per_thread *pt = &cx->pt[tsi];
|
|
|
|
|
|
|
|
return pt->evlib_pt;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_callback_all_protocol_vhost_args(struct lws_vhost *vh,
|
|
|
|
const struct lws_protocols *protocol, int reason,
|
|
|
|
void *argp, size_t len)
|
|
|
|
{
|
|
|
|
struct lws_context *context = vh->context;
|
|
|
|
struct lws_context_per_thread *pt = &context->pt[0];
|
|
|
|
unsigned int n, m = context->count_threads;
|
|
|
|
struct lws *wsi;
|
|
|
|
|
|
|
|
while (m--) {
|
|
|
|
for (n = 0; n < pt->fds_count; n++) {
|
|
|
|
wsi = wsi_from_fd(context, pt->fds[n].fd);
|
2024-03-26 22:15:45 +01:00
|
|
|
|
|
|
|
if (!wsi || !wsi->a.protocol || wsi->a.vhost != vh)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (protocol &&
|
|
|
|
wsi->a.protocol->callback != protocol->callback &&
|
|
|
|
strcmp(protocol->name, wsi->a.protocol->name))
|
2019-01-13 06:58:21 +08:00
|
|
|
continue;
|
2024-03-26 22:15:45 +01:00
|
|
|
|
|
|
|
wsi->a.protocol->callback(wsi, (enum lws_callback_reasons)reason,
|
|
|
|
wsi->user_space, argp, len);
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
pt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_callback_all_protocol_vhost(struct lws_vhost *vh,
|
|
|
|
const struct lws_protocols *protocol, int reason)
|
|
|
|
{
|
|
|
|
return lws_callback_all_protocol_vhost_args(vh, protocol, reason, NULL, 0);
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2020-12-12 06:21:40 +00:00
|
|
|
lws_callback_vhost_protocols(struct lws *wsi, int reason, void *in, size_t len)
|
2019-01-13 06:58:21 +08:00
|
|
|
{
|
|
|
|
int n;
|
|
|
|
|
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
|
|
|
for (n = 0; n < wsi->a.vhost->count_protocols; n++)
|
2020-12-12 06:21:40 +00:00
|
|
|
if (wsi->a.vhost->protocols[n].callback(wsi, (enum lws_callback_reasons)reason, NULL, in, len))
|
2019-01-13 06:58:21 +08:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-06-29 13:30:48 +01:00
|
|
|
#if defined(LWS_WITH_SYS_FAULT_INJECTION)
|
|
|
|
/*
|
|
|
|
* We want to inject a fault that makes it feel like the peer hung up on us,
|
|
|
|
* or we were otherwise cut off.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
lws_wsi_fault_timedclose_cb(lws_sorted_usec_list_t *s)
|
|
|
|
{
|
|
|
|
struct lws *wsi = lws_container_of(s, struct lws, sul_fault_timedclose);
|
|
|
|
|
|
|
|
lwsl_wsi_warn(wsi, "force-closing");
|
|
|
|
lws_wsi_close(wsi, LWS_TO_KILL_ASYNC);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(LWS_WITH_SYS_FAULT_INJECTION)
|
|
|
|
void
|
|
|
|
lws_wsi_fault_timedclose(struct lws *wsi)
|
|
|
|
{
|
|
|
|
uint64_t u;
|
|
|
|
|
|
|
|
if (!lws_fi(&wsi->fic, "timedclose"))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (lws_fi_range(&wsi->fic, "timedclose_ms", &u))
|
|
|
|
return;
|
|
|
|
|
|
|
|
lwsl_wsi_warn(wsi, "injecting close in %ums", (unsigned int)u);
|
|
|
|
lws_sul_schedule(wsi->a.context, wsi->tsi, &wsi->sul_fault_timedclose,
|
|
|
|
lws_wsi_fault_timedclose_cb,
|
|
|
|
(lws_usec_t)(u * 1000ull));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2020-12-24 16:06:50 +00:00
|
|
|
/*
|
|
|
|
* We need the context lock
|
|
|
|
*/
|
|
|
|
|
2020-10-04 07:28:41 +01:00
|
|
|
struct lws *
|
2020-12-24 16:06:50 +00:00
|
|
|
__lws_wsi_create_with_role(struct lws_context *context, int tsi,
|
2021-06-26 17:24:19 +01:00
|
|
|
const struct lws_role_ops *ops,
|
|
|
|
lws_log_cx_t *log_cx_template)
|
2020-10-04 07:28:41 +01:00
|
|
|
{
|
|
|
|
size_t s = sizeof(struct lws);
|
|
|
|
struct lws *wsi;
|
|
|
|
|
2020-12-25 05:54:19 +00:00
|
|
|
assert(tsi >= 0 && tsi < LWS_MAX_SMP);
|
|
|
|
|
2020-12-24 16:06:50 +00:00
|
|
|
lws_context_assert_lock_held(context);
|
|
|
|
|
2020-10-04 07:28:41 +01:00
|
|
|
#if defined(LWS_WITH_EVENT_LIBS)
|
|
|
|
s += context->event_loop_ops->evlib_size_wsi;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
wsi = lws_zalloc(s, __func__);
|
|
|
|
|
|
|
|
if (!wsi) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_cx_err(context, "OOM");
|
2020-10-04 07:28:41 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-06-26 17:24:19 +01:00
|
|
|
if (log_cx_template)
|
|
|
|
wsi->lc.log_cx = log_cx_template;
|
|
|
|
else
|
|
|
|
wsi->lc.log_cx = context->log_cx;
|
|
|
|
|
2020-10-04 07:28:41 +01:00
|
|
|
#if defined(LWS_WITH_EVENT_LIBS)
|
|
|
|
wsi->evlib_wsi = (uint8_t *)wsi + sizeof(*wsi);
|
|
|
|
#endif
|
|
|
|
wsi->a.context = context;
|
|
|
|
lws_role_transition(wsi, 0, LRS_UNCONNECTED, ops);
|
2020-12-24 16:06:50 +00:00
|
|
|
wsi->pending_timeout = NO_PENDING_TIMEOUT;
|
2020-10-04 07:28:41 +01:00
|
|
|
wsi->a.protocol = NULL;
|
2020-12-12 06:21:40 +00:00
|
|
|
wsi->tsi = (char)tsi;
|
2020-10-04 07:28:41 +01:00
|
|
|
wsi->a.vhost = NULL;
|
|
|
|
wsi->desc.sockfd = LWS_SOCK_INVALID;
|
2020-12-24 16:06:50 +00:00
|
|
|
wsi->position_in_fds_table = LWS_NO_FDS_POS;
|
2020-10-04 07:28:41 +01:00
|
|
|
|
2021-03-16 13:32:05 +00:00
|
|
|
#if defined(LWS_WITH_SYS_FAULT_INJECTION)
|
|
|
|
lws_xos_init(&wsi->fic.xos, lws_xos(&context->fic.xos));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
lws_fi_inherit_copy(&wsi->fic, &context->fic, "wsi", NULL);
|
|
|
|
|
|
|
|
if (lws_fi(&wsi->fic, "createfail")) {
|
|
|
|
lws_fi_destroy(&wsi->fic);
|
|
|
|
lws_free(wsi);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-10-04 07:28:41 +01:00
|
|
|
return wsi;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
lws_wsi_inject_to_loop(struct lws_context_per_thread *pt, struct lws *wsi)
|
|
|
|
{
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
lws_pt_lock(pt, __func__); /* -------------- pt { */
|
|
|
|
|
|
|
|
if (pt->context->event_loop_ops->sock_accept)
|
|
|
|
if (pt->context->event_loop_ops->sock_accept(wsi))
|
|
|
|
goto bail;
|
|
|
|
|
|
|
|
if (__insert_wsi_socket_into_fds(pt->context, wsi))
|
|
|
|
goto bail;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
bail:
|
|
|
|
lws_pt_unlock(pt);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Take a copy of wsi->desc.sockfd before calling this, then close it
|
|
|
|
* afterwards
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
lws_wsi_extract_from_loop(struct lws *wsi)
|
|
|
|
{
|
|
|
|
if (lws_socket_is_valid(wsi->desc.sockfd))
|
|
|
|
__remove_wsi_socket_from_fds(wsi);
|
|
|
|
|
|
|
|
if (!wsi->a.context->event_loop_ops->destroy_wsi &&
|
|
|
|
wsi->a.context->event_loop_ops->wsi_logical_close) {
|
|
|
|
wsi->a.context->event_loop_ops->wsi_logical_close(wsi);
|
|
|
|
return 1; /* close / destroy continues async */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wsi->a.context->event_loop_ops->destroy_wsi)
|
|
|
|
wsi->a.context->event_loop_ops->destroy_wsi(wsi);
|
|
|
|
|
|
|
|
return 0; /* he is destroyed */
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_callback_vhost_protocols_vhost(struct lws_vhost *vh, int reason, void *in,
|
|
|
|
size_t len)
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
struct lws *wsi = lws_zalloc(sizeof(*wsi), "fake wsi");
|
|
|
|
|
2019-07-13 11:37:46 -07:00
|
|
|
if (!wsi)
|
|
|
|
return 1;
|
|
|
|
|
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 = vh->context;
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_vhost_bind_wsi(vh, wsi);
|
|
|
|
|
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
|
|
|
for (n = 0; n < wsi->a.vhost->count_protocols; n++) {
|
|
|
|
wsi->a.protocol = &vh->protocols[n];
|
2020-12-12 06:21:40 +00:00
|
|
|
if (wsi->a.protocol->callback(wsi, (enum lws_callback_reasons)reason, NULL, in, len)) {
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_free(wsi);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lws_free(wsi);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_rx_flow_control(struct lws *wsi, int _enable)
|
|
|
|
{
|
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
|
|
|
struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
|
2019-01-13 06:58:21 +08:00
|
|
|
int en = _enable;
|
|
|
|
|
|
|
|
// h2 ignores rx flow control atm
|
2019-12-23 11:31:57 +00:00
|
|
|
if (lwsi_role_h2(wsi) || wsi->mux_substream ||
|
2019-01-13 06:58:21 +08:00
|
|
|
lwsi_role_h2_ENCAPSULATION(wsi))
|
|
|
|
return 0; // !!!
|
|
|
|
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_info(wsi, "0x%x", _enable);
|
2019-01-13 06:58:21 +08:00
|
|
|
|
|
|
|
if (!(_enable & LWS_RXFLOW_REASON_APPLIES)) {
|
|
|
|
/*
|
|
|
|
* convert user bool style to bitmap style... in user simple
|
|
|
|
* bool style _enable = 0 = flow control it, = 1 = allow rx
|
|
|
|
*/
|
|
|
|
en = LWS_RXFLOW_REASON_APPLIES | LWS_RXFLOW_REASON_USER_BOOL;
|
|
|
|
if (_enable & 1)
|
|
|
|
en |= LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
lws_pt_lock(pt, __func__);
|
|
|
|
|
|
|
|
/* any bit set in rxflow_bitmap DISABLEs rxflow control */
|
|
|
|
if (en & LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT)
|
2021-01-06 15:08:22 +00:00
|
|
|
wsi->rxflow_bitmap = (uint8_t)(wsi->rxflow_bitmap & ~(en & 0xff));
|
2019-01-13 06:58:21 +08:00
|
|
|
else
|
2021-01-06 15:08:22 +00:00
|
|
|
wsi->rxflow_bitmap = (uint8_t)(wsi->rxflow_bitmap | (en & 0xff));
|
2019-01-13 06:58:21 +08:00
|
|
|
|
|
|
|
if ((LWS_RXFLOW_PENDING_CHANGE | (!wsi->rxflow_bitmap)) ==
|
|
|
|
wsi->rxflow_change_to)
|
|
|
|
goto skip;
|
|
|
|
|
|
|
|
wsi->rxflow_change_to = LWS_RXFLOW_PENDING_CHANGE |
|
|
|
|
(!wsi->rxflow_bitmap);
|
|
|
|
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_info(wsi, "bitmap 0x%x: en 0x%x, ch 0x%x",
|
|
|
|
wsi->rxflow_bitmap, en, wsi->rxflow_change_to);
|
2019-01-13 06:58:21 +08:00
|
|
|
|
|
|
|
if (_enable & LWS_RXFLOW_REASON_FLAG_PROCESS_NOW ||
|
|
|
|
!wsi->rxflow_will_be_applied) {
|
|
|
|
en = __lws_rx_flow_control(wsi);
|
|
|
|
lws_pt_unlock(pt);
|
|
|
|
|
|
|
|
return en;
|
|
|
|
}
|
|
|
|
|
|
|
|
skip:
|
|
|
|
lws_pt_unlock(pt);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
void
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_rx_flow_allow_all_protocol(const struct lws_context *context,
|
|
|
|
const struct lws_protocols *protocol)
|
|
|
|
{
|
|
|
|
const struct lws_context_per_thread *pt = &context->pt[0];
|
|
|
|
struct lws *wsi;
|
|
|
|
unsigned int n, m = context->count_threads;
|
|
|
|
|
|
|
|
while (m--) {
|
|
|
|
for (n = 0; n < pt->fds_count; n++) {
|
|
|
|
wsi = wsi_from_fd(context, pt->fds[n].fd);
|
2024-03-26 22:15:45 +01:00
|
|
|
if (!wsi || !wsi->a.protocol)
|
2019-01-13 06:58:21 +08:00
|
|
|
continue;
|
2024-03-26 22:15:45 +01:00
|
|
|
if (wsi->a.protocol->callback == protocol->callback &&
|
|
|
|
!strcmp(protocol->name, wsi->a.protocol->name))
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_rx_flow_control(wsi, LWS_RXFLOW_ALLOW);
|
|
|
|
}
|
|
|
|
pt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int user_callback_handle_rxflow(lws_callback_function callback_function,
|
|
|
|
struct lws *wsi,
|
|
|
|
enum lws_callback_reasons reason, void *user,
|
|
|
|
void *in, size_t len)
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
|
|
|
|
wsi->rxflow_will_be_applied = 1;
|
|
|
|
n = callback_function(wsi, reason, user, in, len);
|
|
|
|
wsi->rxflow_will_be_applied = 0;
|
|
|
|
if (!n)
|
|
|
|
n = __lws_rx_flow_control(wsi);
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2019-01-13 06:58:21 +08:00
|
|
|
__lws_rx_flow_control(struct lws *wsi)
|
|
|
|
{
|
|
|
|
struct lws *wsic = wsi->child_list;
|
|
|
|
|
|
|
|
// h2 ignores rx flow control atm
|
2019-12-23 11:31:57 +00:00
|
|
|
if (lwsi_role_h2(wsi) || wsi->mux_substream ||
|
2019-01-13 06:58:21 +08:00
|
|
|
lwsi_role_h2_ENCAPSULATION(wsi))
|
|
|
|
return 0; // !!!
|
|
|
|
|
|
|
|
/* if he has children, do those if they were changed */
|
|
|
|
while (wsic) {
|
|
|
|
if (wsic->rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE)
|
|
|
|
__lws_rx_flow_control(wsic);
|
|
|
|
|
|
|
|
wsic = wsic->sibling_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* there is no pending change */
|
|
|
|
if (!(wsi->rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* stuff is still buffered, not ready to really accept new input */
|
|
|
|
if (lws_buflist_next_segment_len(&wsi->buflist, NULL)) {
|
|
|
|
/* get ourselves called back to deal with stashed buffer */
|
|
|
|
lws_callback_on_writable(wsi);
|
2019-05-04 13:19:12 +01:00
|
|
|
// return 0;
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* now the pending is cleared, we can change rxflow state */
|
|
|
|
|
2020-12-12 06:21:40 +00:00
|
|
|
wsi->rxflow_change_to &= (~LWS_RXFLOW_PENDING_CHANGE) & 3;
|
2019-01-13 06:58:21 +08:00
|
|
|
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_info(wsi, "rxflow: change_to %d",
|
|
|
|
wsi->rxflow_change_to & LWS_RXFLOW_ALLOW);
|
2019-01-13 06:58:21 +08:00
|
|
|
|
|
|
|
/* adjust the pollfd for this wsi */
|
|
|
|
|
|
|
|
if (wsi->rxflow_change_to & LWS_RXFLOW_ALLOW) {
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_info(wsi, "reenable POLLIN");
|
2019-09-12 05:41:19 +01:00
|
|
|
// lws_buflist_describe(&wsi->buflist, NULL, __func__);
|
2019-01-13 06:58:21 +08:00
|
|
|
if (__lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_info(wsi, "fail");
|
2019-01-13 06:58:21 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
if (__lws_change_pollfd(wsi, LWS_POLLIN, 0))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
const struct lws_protocols *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_protocol(struct lws *wsi)
|
|
|
|
{
|
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
|
|
|
return wsi->a.protocol;
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
lws_ensure_user_space(struct lws *wsi)
|
|
|
|
{
|
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)
|
2019-01-13 06:58:21 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* allocate the per-connection user memory (if any) */
|
|
|
|
|
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->per_session_data_size && !wsi->user_space) {
|
2019-01-13 06:58:21 +08:00
|
|
|
wsi->user_space = lws_zalloc(
|
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->per_session_data_size, "user space");
|
2019-01-13 06:58:21 +08:00
|
|
|
if (wsi->user_space == NULL) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_err(wsi, "OOM");
|
2019-01-13 06:58:21 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
} else
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_debug(wsi, "protocol pss %lu, user_space=%p",
|
2021-06-28 05:05:57 +01:00
|
|
|
(long)wsi->a.protocol->per_session_data_size,
|
|
|
|
wsi->user_space);
|
2019-01-13 06:58:21 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
void *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_adjust_protocol_psds(struct lws *wsi, size_t new_size)
|
|
|
|
{
|
|
|
|
((struct lws_protocols *)lws_get_protocol(wsi))->per_session_data_size =
|
|
|
|
new_size;
|
|
|
|
|
|
|
|
if (lws_ensure_user_space(wsi))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return wsi->user_space;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2019-10-29 13:06:15 +04:00
|
|
|
lws_get_tsi(struct lws *wsi)
|
|
|
|
{
|
|
|
|
return (int)wsi->tsi;
|
|
|
|
}
|
2019-01-13 06:58:21 +08:00
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_is_ssl(struct lws *wsi)
|
|
|
|
{
|
|
|
|
#if defined(LWS_WITH_TLS)
|
|
|
|
return wsi->tls.use_ssl & LCCSCF_USE_SSL;
|
|
|
|
#else
|
|
|
|
(void)wsi;
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS)
|
2020-01-02 08:32:23 +00:00
|
|
|
lws_tls_conn*
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_ssl(struct lws *wsi)
|
|
|
|
{
|
|
|
|
return wsi->tls.ssl;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-09-13 15:10:42 +01:00
|
|
|
int
|
|
|
|
lws_has_buffered_out(struct lws *wsi)
|
|
|
|
{
|
|
|
|
if (wsi->buflist_out)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
#if defined(LWS_ROLE_H2)
|
|
|
|
{
|
|
|
|
struct lws *nwsi = lws_get_network_wsi(wsi);
|
|
|
|
|
|
|
|
if (nwsi->buflist_out)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_partial_buffered(struct lws *wsi)
|
|
|
|
{
|
|
|
|
return lws_has_buffered_out(wsi);
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
lws_fileofs_t
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_peer_write_allowance(struct lws *wsi)
|
|
|
|
{
|
roles: compress role ops structs
role ops are usually only sparsely filled, there are currently 20
function pointers but several roles only fill in two. No single
role has more than 14 of the ops. On a 32/64 bit build this part
of the ops struct takes a fixed 80 / 160 bytes then.
First reduce the type of the callback reason part from uint16_t to
uint8_t, this saves 12 bytes unconditionally.
Change to a separate function pointer array with a nybble index
array, it costs 10 bytes for the index and a pointer to the
separate array, for 32-bit the cost is
2 + (4 x ops_used)
and for 64-bit
6 + (8 x ops_used)
for 2 x ops_used it means 32-bit: 10 vs 80 / 64-bit: 22 vs 160
For a typical system with h1 (9), h2 (14), listen (2), netlink (2),
pipe (1), raw_skt (3), ws (12), == 43 ops_used out of 140, it means
the .rodata for this reduced from 32-bit: 560 -> 174 (386 byte
saving) and 64-bit: 1120 -> 350 (770 byte saving)
This doesn't account for the changed function ops calling code, two
ways were tried, a preprocessor macro and explicit functions
For an x86_64 gcc 10 build with most options, release mode,
.text + .rodata
before patch: 553282
accessor macro: 552714 (568 byte saving)
accessor functions: 553674 (392 bytes worse than without patch)
therefore we went with the macros
2020-10-19 13:55:21 +01:00
|
|
|
if (!lws_rops_fidx(wsi->role_ops, LWS_ROPS_tx_credit))
|
2019-01-13 06:58:21 +08:00
|
|
|
return -1;
|
roles: compress role ops structs
role ops are usually only sparsely filled, there are currently 20
function pointers but several roles only fill in two. No single
role has more than 14 of the ops. On a 32/64 bit build this part
of the ops struct takes a fixed 80 / 160 bytes then.
First reduce the type of the callback reason part from uint16_t to
uint8_t, this saves 12 bytes unconditionally.
Change to a separate function pointer array with a nybble index
array, it costs 10 bytes for the index and a pointer to the
separate array, for 32-bit the cost is
2 + (4 x ops_used)
and for 64-bit
6 + (8 x ops_used)
for 2 x ops_used it means 32-bit: 10 vs 80 / 64-bit: 22 vs 160
For a typical system with h1 (9), h2 (14), listen (2), netlink (2),
pipe (1), raw_skt (3), ws (12), == 43 ops_used out of 140, it means
the .rodata for this reduced from 32-bit: 560 -> 174 (386 byte
saving) and 64-bit: 1120 -> 350 (770 byte saving)
This doesn't account for the changed function ops calling code, two
ways were tried, a preprocessor macro and explicit functions
For an x86_64 gcc 10 build with most options, release mode,
.text + .rodata
before patch: 553282
accessor macro: 552714 (568 byte saving)
accessor functions: 553674 (392 bytes worse than without patch)
therefore we went with the macros
2020-10-19 13:55:21 +01:00
|
|
|
|
|
|
|
return lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_tx_credit).
|
|
|
|
tx_credit(wsi, LWSTXCR_US_TO_PEER, 0);
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
void
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_role_transition(struct lws *wsi, enum lwsi_role role, enum lwsi_state state,
|
|
|
|
const struct lws_role_ops *ops)
|
|
|
|
{
|
2020-04-22 06:32:15 +01:00
|
|
|
#if (_LWS_ENABLED_LOGS & LLL_DEBUG)
|
2019-01-13 06:58:21 +08:00
|
|
|
const char *name = "(unset)";
|
|
|
|
#endif
|
2020-12-12 06:21:40 +00:00
|
|
|
wsi->wsistate = (unsigned int)role | (unsigned int)state;
|
2019-01-13 06:58:21 +08:00
|
|
|
if (ops)
|
|
|
|
wsi->role_ops = ops;
|
2020-04-22 06:32:15 +01:00
|
|
|
#if (_LWS_ENABLED_LOGS & LLL_DEBUG)
|
2019-01-13 06:58:21 +08:00
|
|
|
if (wsi->role_ops)
|
|
|
|
name = wsi->role_ops->name;
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_debug(wsi, "wsistate 0x%lx, ops %s",
|
2021-06-28 05:05:57 +01:00
|
|
|
(unsigned long)wsi->wsistate, name);
|
2019-01-13 06:58:21 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_parse_uri(char *p, const char **prot, const char **ads, int *port,
|
|
|
|
const char **path)
|
|
|
|
{
|
|
|
|
const char *end;
|
|
|
|
char unix_skt = 0;
|
|
|
|
|
|
|
|
/* cut up the location into address, port and path */
|
|
|
|
*prot = p;
|
|
|
|
while (*p && (*p != ':' || p[1] != '/' || p[2] != '/'))
|
|
|
|
p++;
|
|
|
|
if (!*p) {
|
|
|
|
end = p;
|
|
|
|
p = (char *)*prot;
|
|
|
|
*prot = end;
|
|
|
|
} else {
|
|
|
|
*p = '\0';
|
|
|
|
p += 3;
|
|
|
|
}
|
|
|
|
if (*p == '+') /* unix skt */
|
|
|
|
unix_skt = 1;
|
|
|
|
|
|
|
|
*ads = p;
|
|
|
|
if (!strcmp(*prot, "http") || !strcmp(*prot, "ws"))
|
|
|
|
*port = 80;
|
|
|
|
else if (!strcmp(*prot, "https") || !strcmp(*prot, "wss"))
|
|
|
|
*port = 443;
|
|
|
|
|
|
|
|
if (*p == '[') {
|
|
|
|
++(*ads);
|
|
|
|
while (*p && *p != ']')
|
|
|
|
p++;
|
|
|
|
if (*p)
|
|
|
|
*p++ = '\0';
|
|
|
|
} else
|
|
|
|
while (*p && *p != ':' && (unix_skt || *p != '/'))
|
|
|
|
p++;
|
|
|
|
|
|
|
|
if (*p == ':') {
|
|
|
|
*p++ = '\0';
|
|
|
|
*port = atoi(p);
|
|
|
|
while (*p && *p != '/')
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
*path = "/";
|
|
|
|
if (*p) {
|
|
|
|
*p++ = '\0';
|
|
|
|
if (*p)
|
|
|
|
*path = p;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ... */
|
|
|
|
|
2021-04-08 15:26:23 +01:00
|
|
|
int
|
|
|
|
lws_get_urlarg_by_name_safe(struct lws *wsi, const char *name, char *buf, int len)
|
2019-01-13 06:58:21 +08:00
|
|
|
{
|
2021-04-08 15:26:23 +01:00
|
|
|
int n = 0, fraglen, sl = (int)strlen(name);
|
|
|
|
|
|
|
|
do {
|
|
|
|
fraglen = lws_hdr_copy_fragment(wsi, buf, len,
|
|
|
|
WSI_TOKEN_HTTP_URI_ARGS, n);
|
|
|
|
|
2024-09-28 06:01:36 +01:00
|
|
|
if (fraglen == -1) /* no fragment or basic problem */
|
2021-04-08 15:26:23 +01:00
|
|
|
break;
|
2019-01-13 06:58:21 +08:00
|
|
|
|
2024-09-28 06:01:36 +01:00
|
|
|
if (fraglen > 0 && /* fragment could fit */
|
|
|
|
fraglen + 1 < len &&
|
2021-04-08 15:26:23 +01:00
|
|
|
fraglen >= sl &&
|
|
|
|
!strncmp(buf, name, (size_t)sl)) {
|
|
|
|
/*
|
|
|
|
* If he left off the trailing =, trim it from the
|
|
|
|
* result
|
|
|
|
*/
|
2019-01-13 06:58:21 +08:00
|
|
|
|
2021-04-08 15:26:23 +01:00
|
|
|
if (name[sl - 1] != '=' &&
|
|
|
|
sl < fraglen &&
|
|
|
|
buf[sl] == '=')
|
|
|
|
sl++;
|
|
|
|
|
|
|
|
memmove(buf, buf + sl, (size_t)(fraglen - sl));
|
|
|
|
buf[fraglen - sl] = '\0';
|
|
|
|
|
|
|
|
return fraglen - sl;
|
|
|
|
}
|
2019-01-13 06:58:21 +08:00
|
|
|
|
|
|
|
n++;
|
2021-04-08 15:26:23 +01:00
|
|
|
} while (1);
|
2019-01-13 06:58:21 +08:00
|
|
|
|
2021-04-08 15:26:23 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
lws_get_urlarg_by_name(struct lws *wsi, const char *name, char *buf, int len)
|
|
|
|
{
|
|
|
|
int n = lws_get_urlarg_by_name_safe(wsi, name, buf, len);
|
|
|
|
|
|
|
|
return n < 0 ? NULL : buf;
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(LWS_WITHOUT_EXTENSIONS)
|
|
|
|
|
|
|
|
/* we need to provide dummy callbacks for internal exts
|
|
|
|
* so user code runs when faced with a lib compiled with
|
|
|
|
* extensions disabled.
|
|
|
|
*/
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_extension_callback_pm_deflate(struct lws_context *context,
|
|
|
|
const struct lws_extension *ext,
|
|
|
|
struct lws *wsi,
|
|
|
|
enum lws_extension_callback_reasons reason,
|
|
|
|
void *user, void *in, size_t len)
|
|
|
|
{
|
|
|
|
(void)context;
|
|
|
|
(void)ext;
|
|
|
|
(void)wsi;
|
|
|
|
(void)reason;
|
|
|
|
(void)user;
|
|
|
|
(void)in;
|
|
|
|
(void)len;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_set_extension_option(struct lws *wsi, const char *ext_name,
|
|
|
|
const char *opt_name, const char *opt_val)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_is_cgi(struct lws *wsi) {
|
|
|
|
#ifdef LWS_WITH_CGI
|
|
|
|
return !!wsi->http.cgi;
|
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
const struct lws_protocol_vhost_options *
|
|
|
|
lws_pvo_search(const struct lws_protocol_vhost_options *pvo, const char *name)
|
|
|
|
{
|
|
|
|
while (pvo) {
|
|
|
|
if (!strcmp(pvo->name, name))
|
|
|
|
break;
|
|
|
|
|
|
|
|
pvo = pvo->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pvo;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
lws_pvo_get_str(void *in, const char *name, const char **result)
|
|
|
|
{
|
|
|
|
const struct lws_protocol_vhost_options *pv =
|
|
|
|
lws_pvo_search((const struct lws_protocol_vhost_options *)in,
|
|
|
|
name);
|
|
|
|
|
|
|
|
if (!pv)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
*result = (const char *)pv->value;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2019-08-09 10:12:09 +01:00
|
|
|
lws_broadcast(struct lws_context_per_thread *pt, int reason, void *in, size_t len)
|
2019-01-13 06:58:21 +08:00
|
|
|
{
|
2019-08-09 10:12:09 +01:00
|
|
|
struct lws_vhost *v = pt->context->vhost_list;
|
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
|
|
|
lws_fakewsi_def_plwsa(pt);
|
2019-01-13 06:58:21 +08:00
|
|
|
int n, ret = 0;
|
|
|
|
|
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
|
|
|
lws_fakewsi_prep_plwsa_ctx(pt->context);
|
2020-10-01 10:39:43 +01:00
|
|
|
#if !defined(LWS_PLAT_FREERTOS) && LWS_MAX_SMP > 1
|
2020-12-12 06:21:40 +00:00
|
|
|
((struct lws *)plwsa)->tsi = (char)(int)(pt - &pt->context->pt[0]);
|
2020-10-01 10:39:43 +01:00
|
|
|
#endif
|
2019-01-13 06:58:21 +08:00
|
|
|
|
|
|
|
while (v) {
|
|
|
|
const struct lws_protocols *p = v->protocols;
|
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
|
|
|
|
|
|
|
plwsa->vhost = v; /* not a real bound wsi */
|
2019-01-13 06:58:21 +08:00
|
|
|
|
|
|
|
for (n = 0; n < v->count_protocols; n++) {
|
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
|
|
|
plwsa->protocol = p;
|
2019-01-13 06:58:21 +08:00
|
|
|
if (p->callback &&
|
2020-12-12 06:21:40 +00:00
|
|
|
p->callback((struct lws *)plwsa, (enum lws_callback_reasons)reason, NULL, in, len))
|
2019-01-13 06:58:21 +08:00
|
|
|
ret |= 1;
|
|
|
|
p++;
|
|
|
|
}
|
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
|
|
|
|
2019-01-13 06:58:21 +08:00
|
|
|
v = v->vhost_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
void *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_wsi_user(struct lws *wsi)
|
|
|
|
{
|
|
|
|
return wsi->user_space;
|
|
|
|
}
|
|
|
|
|
2020-10-01 10:30:00 +01:00
|
|
|
int
|
|
|
|
lws_wsi_tsi(struct lws *wsi)
|
|
|
|
{
|
|
|
|
return wsi->tsi;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
void
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_set_wsi_user(struct lws *wsi, void *data)
|
|
|
|
{
|
2020-03-18 12:19:51 +00:00
|
|
|
if (!wsi->user_space_externally_allocated && wsi->user_space)
|
|
|
|
lws_free(wsi->user_space);
|
|
|
|
|
|
|
|
wsi->user_space_externally_allocated = 1;
|
|
|
|
wsi->user_space = data;
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
struct lws *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_parent(const struct lws *wsi)
|
|
|
|
{
|
|
|
|
return wsi->parent;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
struct lws *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_child(const struct lws *wsi)
|
|
|
|
{
|
|
|
|
return wsi->child_list;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
void *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_opaque_parent_data(const struct lws *wsi)
|
|
|
|
{
|
|
|
|
return wsi->opaque_parent_data;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
void
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_set_opaque_parent_data(struct lws *wsi, void *data)
|
|
|
|
{
|
|
|
|
wsi->opaque_parent_data = data;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
void *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_opaque_user_data(const struct lws *wsi)
|
|
|
|
{
|
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
|
|
|
return wsi->a.opaque_user_data;
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
void
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_set_opaque_user_data(struct lws *wsi, void *data)
|
|
|
|
{
|
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.opaque_user_data = data;
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_child_pending_on_writable(const struct lws *wsi)
|
|
|
|
{
|
|
|
|
return wsi->parent_pending_cb_on_writable;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
void
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_clear_child_pending_on_writable(struct lws *wsi)
|
|
|
|
{
|
|
|
|
wsi->parent_pending_cb_on_writable = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
const char *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_vhost_name(struct lws_vhost *vhost)
|
|
|
|
{
|
|
|
|
return vhost->name;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_vhost_port(struct lws_vhost *vhost)
|
|
|
|
{
|
|
|
|
return vhost->listen_port;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
void *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_vhost_user(struct lws_vhost *vhost)
|
|
|
|
{
|
|
|
|
return vhost->user;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
const char *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_vhost_iface(struct lws_vhost *vhost)
|
|
|
|
{
|
|
|
|
return vhost->iface;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
lws_sockfd_type
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_socket_fd(struct lws *wsi)
|
|
|
|
{
|
|
|
|
if (!wsi)
|
|
|
|
return -1;
|
|
|
|
return wsi->desc.sockfd;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
struct lws_vhost *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_vhost_get(struct lws *wsi)
|
|
|
|
{
|
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
|
|
|
return wsi->a.vhost;
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
struct lws_vhost *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_vhost(struct lws *wsi)
|
|
|
|
{
|
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
|
|
|
return wsi->a.vhost;
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
const struct lws_protocols *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_protocol_get(struct lws *wsi)
|
|
|
|
{
|
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
|
|
|
return wsi->a.protocol;
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
2019-09-30 09:42:38 -07:00
|
|
|
#if defined(LWS_WITH_UDP)
|
2020-01-02 08:32:23 +00:00
|
|
|
const struct lws_udp *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_udp(const struct lws *wsi)
|
|
|
|
{
|
|
|
|
return wsi->udp;
|
|
|
|
}
|
2019-09-30 09:42:38 -07:00
|
|
|
#endif
|
2019-01-13 06:58:21 +08:00
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
struct lws_context *
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_get_context(const struct lws *wsi)
|
|
|
|
{
|
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
|
|
|
return wsi->a.context;
|
2019-01-13 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
2021-06-26 17:24:19 +01:00
|
|
|
struct lws_log_cx *
|
|
|
|
lwsl_wsi_get_cx(struct lws *wsi)
|
|
|
|
{
|
|
|
|
if (!wsi)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return wsi->lc.log_cx;
|
|
|
|
}
|
|
|
|
|
2019-09-23 04:23:07 -07:00
|
|
|
#if defined(LWS_WITH_CLIENT)
|
|
|
|
int
|
2020-04-15 20:57:00 +01:00
|
|
|
_lws_generic_transaction_completed_active_conn(struct lws **_wsi, char take_vh_lock)
|
2019-09-23 04:23:07 -07:00
|
|
|
{
|
2020-01-30 13:19:11 +00:00
|
|
|
struct lws *wnew, *wsi = *_wsi;
|
2019-09-23 04:23:07 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Are we constitutionally capable of having a queue, ie, we are on
|
|
|
|
* the "active client connections" list?
|
|
|
|
*
|
|
|
|
* If not, that's it for us.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (lws_dll2_is_detached(&wsi->dll_cli_active_conns))
|
|
|
|
return 0; /* no new transaction */
|
|
|
|
|
|
|
|
/*
|
2020-01-30 13:19:11 +00:00
|
|
|
* With h1 queuing, the original "active client" moves his attributes
|
|
|
|
* like fd, ssl, queue and active client list entry to the next guy in
|
|
|
|
* the queue before closing... it's because the user code knows the
|
|
|
|
* individual wsi and the action must take place in the correct wsi
|
|
|
|
* context. Note this means we don't truly pipeline headers.
|
|
|
|
*
|
|
|
|
* Trying to keep the original "active client" in place to do the work
|
|
|
|
* of the wsi breaks down when dealing with queued POSTs otherwise; it's
|
|
|
|
* also competing with the real mux child arrangements and complicating
|
|
|
|
* the code.
|
|
|
|
*
|
|
|
|
* For that reason, see if we have any queued child now...
|
2019-09-23 04:23:07 -07:00
|
|
|
*/
|
2020-01-30 13:19:11 +00:00
|
|
|
|
|
|
|
if (!wsi->dll2_cli_txn_queue_owner.head) {
|
2019-09-23 04:23:07 -07:00
|
|
|
/*
|
|
|
|
* Nothing pipelined... we should hang around a bit
|
2020-01-30 13:19:11 +00:00
|
|
|
* in case something turns up... otherwise we'll close
|
2019-09-23 04:23:07 -07:00
|
|
|
*/
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_info(wsi, "nothing pipelined waiting");
|
2019-09-23 04:23:07 -07:00
|
|
|
lwsi_set_state(wsi, LRS_IDLING);
|
|
|
|
|
2020-05-06 07:53:41 +01:00
|
|
|
lws_set_timeout(wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE,
|
|
|
|
wsi->keep_warm_secs);
|
2019-09-23 04:23:07 -07:00
|
|
|
|
|
|
|
return 0; /* no new transaction right now */
|
|
|
|
}
|
|
|
|
|
2020-01-30 13:19:11 +00:00
|
|
|
/*
|
|
|
|
* We have a queued child wsi we should bequeath our assets to, before
|
|
|
|
* closing ourself
|
|
|
|
*/
|
|
|
|
|
2020-04-15 20:57:00 +01:00
|
|
|
if (take_vh_lock)
|
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
|
|
|
lws_vhost_lock(wsi->a.vhost);
|
2020-01-30 13:19:11 +00:00
|
|
|
|
|
|
|
wnew = lws_container_of(wsi->dll2_cli_txn_queue_owner.head, struct lws,
|
|
|
|
dll2_cli_txn_queue);
|
|
|
|
|
|
|
|
assert(wsi != wnew);
|
|
|
|
|
|
|
|
lws_dll2_remove(&wnew->dll2_cli_txn_queue);
|
|
|
|
|
|
|
|
assert(lws_socket_is_valid(wsi->desc.sockfd));
|
|
|
|
|
2020-03-10 19:11:15 +00:00
|
|
|
__lws_change_pollfd(wsi, LWS_POLLOUT | LWS_POLLIN, 0);
|
|
|
|
|
2020-01-30 13:19:11 +00:00
|
|
|
/* copy the fd */
|
|
|
|
wnew->desc = wsi->desc;
|
|
|
|
|
|
|
|
assert(lws_socket_is_valid(wnew->desc.sockfd));
|
|
|
|
|
|
|
|
/* disconnect the fd from association with old wsi */
|
|
|
|
|
|
|
|
if (__remove_wsi_socket_from_fds(wsi))
|
|
|
|
return -1;
|
2020-05-04 07:24:58 +01: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
|
|
|
sanity_assert_no_wsi_traces(wsi->a.context, wsi);
|
|
|
|
sanity_assert_no_sockfd_traces(wsi->a.context, wsi->desc.sockfd);
|
2020-01-30 13:19:11 +00:00
|
|
|
wsi->desc.sockfd = LWS_SOCK_INVALID;
|
|
|
|
|
2020-05-04 07:24:58 +01:00
|
|
|
__lws_wsi_remove_from_sul(wsi);
|
|
|
|
|
2020-03-10 19:11:15 +00:00
|
|
|
/*
|
|
|
|
* ... we're doing some magic here in terms of handing off the socket
|
|
|
|
* that has been active to a wsi that has not yet itself been active...
|
|
|
|
* depending on the event lib we may need to give a magic spark to the
|
|
|
|
* new guy and snuff out the old guy's magic spark at that level as well
|
|
|
|
*/
|
|
|
|
|
2020-08-27 15:37:14 +01:00
|
|
|
#if defined(LWS_WITH_EVENT_LIBS)
|
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.context->event_loop_ops->destroy_wsi)
|
|
|
|
wsi->a.context->event_loop_ops->destroy_wsi(wsi);
|
|
|
|
if (wsi->a.context->event_loop_ops->sock_accept)
|
|
|
|
wsi->a.context->event_loop_ops->sock_accept(wnew);
|
2020-03-10 19:11:15 +00:00
|
|
|
#endif
|
|
|
|
|
2020-01-30 13:19:11 +00:00
|
|
|
/* point the fd table entry to new guy */
|
|
|
|
|
|
|
|
assert(lws_socket_is_valid(wnew->desc.sockfd));
|
|
|
|
|
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 (__insert_wsi_socket_into_fds(wsi->a.context, wnew))
|
2020-01-30 13:19:11 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
#if defined(LWS_WITH_TLS)
|
|
|
|
/* pass on the tls */
|
|
|
|
|
|
|
|
wnew->tls = wsi->tls;
|
|
|
|
wsi->tls.client_bio = NULL;
|
|
|
|
wsi->tls.ssl = NULL;
|
|
|
|
wsi->tls.use_ssl = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* take over his copy of his endpoint as an active connection */
|
|
|
|
|
2021-06-25 09:13:57 +01:00
|
|
|
if (!wnew->cli_hostname_copy && wsi->cli_hostname_copy) {
|
|
|
|
wnew->cli_hostname_copy = wsi->cli_hostname_copy;
|
|
|
|
wsi->cli_hostname_copy = NULL;
|
|
|
|
}
|
2020-05-06 07:53:41 +01:00
|
|
|
wnew->keep_warm_secs = wsi->keep_warm_secs;
|
2020-01-30 13:19:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* selected queued guy now replaces the original leader on the
|
|
|
|
* active client conn list
|
|
|
|
*/
|
|
|
|
|
|
|
|
lws_dll2_remove(&wsi->dll_cli_active_conns);
|
|
|
|
lws_dll2_add_tail(&wnew->dll_cli_active_conns,
|
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.vhost->dll_cli_active_conns_owner);
|
2020-01-30 13:19:11 +00:00
|
|
|
|
|
|
|
/* move any queued guys to queue on new active conn */
|
|
|
|
|
|
|
|
lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
|
|
|
|
wsi->dll2_cli_txn_queue_owner.head) {
|
|
|
|
struct lws *ww = lws_container_of(d, struct lws,
|
|
|
|
dll2_cli_txn_queue);
|
|
|
|
|
|
|
|
lws_dll2_remove(&ww->dll2_cli_txn_queue);
|
|
|
|
lws_dll2_add_tail(&ww->dll2_cli_txn_queue,
|
|
|
|
&wnew->dll2_cli_txn_queue_owner);
|
|
|
|
|
|
|
|
} lws_end_foreach_dll_safe(d, d1);
|
|
|
|
|
2020-04-15 20:57:00 +01:00
|
|
|
if (take_vh_lock)
|
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
|
|
|
lws_vhost_unlock(wsi->a.vhost);
|
2020-01-30 13:19:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The original leader who passed on all his powers already can die...
|
|
|
|
* in the call stack above us there are guys who still want to touch
|
|
|
|
* him, so have him die next time around the event loop, not now.
|
|
|
|
*/
|
|
|
|
|
|
|
|
wsi->already_did_cce = 1; /* so the close doesn't trigger a CCE */
|
|
|
|
lws_set_timeout(wsi, 1, LWS_TO_KILL_ASYNC);
|
|
|
|
|
|
|
|
/* after the first one, they can only be coming from the queue */
|
|
|
|
wnew->transaction_from_pipeline_queue = 1;
|
|
|
|
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_notice(wsi, " pipeline queue passed -> %s", lws_wsi_tag(wnew));
|
2020-01-30 13:19:11 +00:00
|
|
|
|
|
|
|
*_wsi = wnew; /* inform caller we swapped */
|
|
|
|
|
2019-09-23 04:23:07 -07:00
|
|
|
return 1; /* new transaction */
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int LWS_WARN_UNUSED_RESULT
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_raw_transaction_completed(struct lws *wsi)
|
|
|
|
{
|
|
|
|
if (lws_has_buffered_out(wsi)) {
|
|
|
|
/*
|
|
|
|
* ...so he tried to send something large, but it went out
|
|
|
|
* as a partial, but he immediately called us to say he wants
|
|
|
|
* to close the connection.
|
|
|
|
*
|
|
|
|
* Defer the close until the last part of the partial is sent.
|
|
|
|
*
|
|
|
|
*/
|
2021-06-18 07:28:23 +01:00
|
|
|
|
|
|
|
lwsl_wsi_debug(wsi, "deferring due to partial");
|
2019-01-13 06:58:21 +08:00
|
|
|
wsi->close_when_buffered_out_drained = 1;
|
|
|
|
lws_callback_on_writable(wsi);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p,
|
|
|
|
const char *reason)
|
|
|
|
{
|
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 == p)
|
2019-01-13 06:58:21 +08:00
|
|
|
// return 0;
|
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
|
|
|
const struct lws_protocols *vp = wsi->a.vhost->protocols, *vpo;
|
2019-01-13 06:58:21 +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 && wsi->protocol_bind_balance) {
|
|
|
|
wsi->a.protocol->callback(wsi,
|
2019-01-13 06:58:21 +08:00
|
|
|
wsi->role_ops->protocol_unbind_cb[!!lwsi_role_server(wsi)],
|
|
|
|
wsi->user_space, (void *)reason, 0);
|
|
|
|
wsi->protocol_bind_balance = 0;
|
|
|
|
}
|
|
|
|
if (!wsi->user_space_externally_allocated)
|
|
|
|
lws_free_set_NULL(wsi->user_space);
|
|
|
|
|
|
|
|
lws_same_vh_protocol_remove(wsi);
|
|
|
|
|
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 = p;
|
2019-01-13 06:58:21 +08:00
|
|
|
if (!p)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (lws_ensure_user_space(wsi))
|
|
|
|
return 1;
|
|
|
|
|
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 (p > vp && p < &vp[wsi->a.vhost->count_protocols])
|
2019-01-13 06:58:21 +08:00
|
|
|
lws_same_vh_protocol_insert(wsi, (int)(p - vp));
|
|
|
|
else {
|
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
|
|
|
int n = wsi->a.vhost->count_protocols;
|
2019-01-13 06:58:21 +08:00
|
|
|
int hit = 0;
|
|
|
|
|
|
|
|
vpo = vp;
|
|
|
|
|
|
|
|
while (n--) {
|
|
|
|
if (p->name && vp->name && !strcmp(p->name, vp->name)) {
|
|
|
|
hit = 1;
|
|
|
|
lws_same_vh_protocol_insert(wsi, (int)(vp - vpo));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
vp++;
|
|
|
|
}
|
|
|
|
if (!hit)
|
|
|
|
lwsl_err("%s: %p is not in vhost '%s' protocols list\n",
|
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
|
|
|
__func__, p, wsi->a.vhost->name);
|
2019-01-13 06:58:21 +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(wsi, wsi->role_ops->protocol_bind_cb[
|
2019-01-13 06:58:21 +08:00
|
|
|
!!lwsi_role_server(wsi)],
|
|
|
|
wsi->user_space, NULL, 0))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
wsi->protocol_bind_balance = 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2019-01-30 20:59:56 +08:00
|
|
|
|
2019-09-13 10:33:24 +01:00
|
|
|
void
|
|
|
|
lws_http_close_immortal(struct lws *wsi)
|
|
|
|
{
|
|
|
|
struct lws *nwsi;
|
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
if (!wsi->mux_substream)
|
2019-09-13 10:33:24 +01:00
|
|
|
return;
|
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
assert(wsi->mux_stream_immortal);
|
|
|
|
wsi->mux_stream_immortal = 0;
|
2019-09-13 10:33:24 +01:00
|
|
|
|
|
|
|
nwsi = lws_get_network_wsi(wsi);
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_debug(wsi, "%s (%d)", lws_wsi_tag(nwsi),
|
|
|
|
nwsi->immortal_substream_count);
|
2019-09-13 10:33:24 +01:00
|
|
|
assert(nwsi->immortal_substream_count);
|
|
|
|
nwsi->immortal_substream_count--;
|
|
|
|
if (!nwsi->immortal_substream_count)
|
|
|
|
/*
|
|
|
|
* since we closed the only immortal stream on this nwsi, we
|
|
|
|
* need to reapply a normal timeout regime to the nwsi
|
|
|
|
*/
|
|
|
|
lws_set_timeout(nwsi, PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE,
|
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.vhost->keepalive_timeout ?
|
|
|
|
wsi->a.vhost->keepalive_timeout : 31);
|
2019-09-13 10:33:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-12-23 11:31:57 +00:00
|
|
|
lws_mux_mark_immortal(struct lws *wsi)
|
2019-09-13 10:33:24 +01:00
|
|
|
{
|
|
|
|
struct lws *nwsi;
|
|
|
|
|
|
|
|
lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
|
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
if (!wsi->mux_substream
|
2019-09-13 10:33:24 +01:00
|
|
|
#if defined(LWS_WITH_CLIENT)
|
2019-12-23 11:31:57 +00:00
|
|
|
&& !wsi->client_mux_substream
|
2019-09-13 10:33:24 +01:00
|
|
|
#endif
|
|
|
|
) {
|
2025-02-25 19:34:27 +00:00
|
|
|
// lwsl_wsi_err(wsi, "not mux substream");
|
2019-09-13 10:33:24 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-08 13:42:52 +00:00
|
|
|
if (wsi->mux_stream_immortal)
|
|
|
|
/* only need to handle it once per child wsi */
|
|
|
|
return;
|
|
|
|
|
2019-09-13 10:33:24 +01:00
|
|
|
nwsi = lws_get_network_wsi(wsi);
|
2020-03-27 19:10:40 +00:00
|
|
|
if (!nwsi)
|
|
|
|
return;
|
2019-09-13 10:33:24 +01:00
|
|
|
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_debug(wsi, "%s (%d)\n", lws_wsi_tag(nwsi),
|
|
|
|
nwsi->immortal_substream_count);
|
2019-09-13 10:33:24 +01:00
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
wsi->mux_stream_immortal = 1;
|
2019-09-13 10:33:24 +01:00
|
|
|
assert(nwsi->immortal_substream_count < 255); /* largest count */
|
|
|
|
nwsi->immortal_substream_count++;
|
|
|
|
if (nwsi->immortal_substream_count == 1)
|
|
|
|
lws_set_timeout(nwsi, NO_PENDING_TIMEOUT, 0);
|
|
|
|
}
|
|
|
|
|
2019-01-30 20:59:56 +08:00
|
|
|
int
|
|
|
|
lws_http_mark_sse(struct lws *wsi)
|
|
|
|
{
|
2020-03-27 19:10:40 +00:00
|
|
|
if (!wsi)
|
|
|
|
return 0;
|
|
|
|
|
2019-01-30 20:59:56 +08:00
|
|
|
lws_http_headers_detach(wsi);
|
2019-12-23 11:31:57 +00:00
|
|
|
lws_mux_mark_immortal(wsi);
|
2019-01-30 20:59:56 +08:00
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
if (wsi->mux_substream)
|
2019-01-30 20:59:56 +08:00
|
|
|
wsi->h2_stream_carries_sse = 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2019-12-23 09:25:56 +00:00
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
#if defined(LWS_WITH_CLIENT)
|
2019-12-23 09:25:56 +00:00
|
|
|
|
|
|
|
const char *
|
|
|
|
lws_wsi_client_stash_item(struct lws *wsi, int stash_idx, int hdr_idx)
|
|
|
|
{
|
|
|
|
/* try the generic client stash */
|
|
|
|
if (wsi->stash)
|
|
|
|
return wsi->stash->cis[stash_idx];
|
|
|
|
|
|
|
|
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
|
|
|
|
/* if not, use the ah stash if applicable */
|
2020-12-12 06:21:40 +00:00
|
|
|
return lws_hdr_simple_ptr(wsi, (enum lws_token_indexes)hdr_idx);
|
2019-12-23 09:25:56 +00:00
|
|
|
#else
|
|
|
|
return NULL;
|
|
|
|
#endif
|
|
|
|
}
|
2019-12-23 11:31:57 +00:00
|
|
|
#endif
|
|
|
|
|
2020-02-25 13:28:25 +00:00
|
|
|
#if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT)
|
2019-12-23 11:31:57 +00:00
|
|
|
|
|
|
|
void
|
2020-12-12 06:21:40 +00:00
|
|
|
lws_wsi_mux_insert(struct lws *wsi, struct lws *parent_wsi, unsigned int sid)
|
2019-12-23 11:31:57 +00:00
|
|
|
{
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_info(wsi, "par %s: assign sid %d (curr %d)",
|
|
|
|
lws_wsi_tag(parent_wsi), sid, wsi->mux.my_sid);
|
2020-04-06 13:22:01 +01:00
|
|
|
|
|
|
|
if (wsi->mux.my_sid && wsi->mux.my_sid != (unsigned int)sid)
|
|
|
|
assert(0);
|
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
wsi->mux.my_sid = sid;
|
|
|
|
wsi->mux.parent_wsi = parent_wsi;
|
|
|
|
wsi->role_ops = parent_wsi->role_ops;
|
|
|
|
|
|
|
|
/* new guy's sibling is whoever was the first child before */
|
|
|
|
wsi->mux.sibling_list = parent_wsi->mux.child_list;
|
|
|
|
|
|
|
|
/* first child is now the new guy */
|
|
|
|
parent_wsi->mux.child_list = wsi;
|
|
|
|
|
|
|
|
parent_wsi->mux.child_count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct lws *
|
|
|
|
lws_wsi_mux_from_id(struct lws *parent_wsi, unsigned int sid)
|
|
|
|
{
|
|
|
|
lws_start_foreach_ll(struct lws *, wsi, parent_wsi->mux.child_list) {
|
|
|
|
if (wsi->mux.my_sid == sid)
|
|
|
|
return wsi;
|
|
|
|
} lws_end_foreach_ll(wsi, mux.sibling_list);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
lws_wsi_mux_dump_children(struct lws *wsi)
|
|
|
|
{
|
|
|
|
#if defined(_DEBUG)
|
|
|
|
if (!wsi->mux.parent_wsi || !lwsl_visible(LLL_INFO))
|
|
|
|
return;
|
|
|
|
|
|
|
|
lws_start_foreach_llp(struct lws **, w,
|
|
|
|
wsi->mux.parent_wsi->mux.child_list) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_info(wsi, " \\---- child %s %s\n",
|
|
|
|
(*w)->role_ops ? (*w)->role_ops->name : "?",
|
|
|
|
lws_wsi_tag(*w));
|
2020-02-25 13:28:25 +00:00
|
|
|
assert(*w != (*w)->mux.sibling_list);
|
2019-12-23 11:31:57 +00:00
|
|
|
} lws_end_foreach_llp(w, mux.sibling_list);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
lws_wsi_mux_close_children(struct lws *wsi, int reason)
|
|
|
|
{
|
|
|
|
struct lws *wsi2;
|
2020-08-18 13:20:44 +01:00
|
|
|
struct lws **w;
|
2019-12-23 11:31:57 +00:00
|
|
|
|
|
|
|
if (!wsi->mux.child_list)
|
|
|
|
return;
|
|
|
|
|
2020-08-18 13:20:44 +01:00
|
|
|
w = &wsi->mux.child_list;
|
|
|
|
while (*w) {
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_info((*w), " closing child");
|
2019-12-23 11:31:57 +00:00
|
|
|
/* disconnect from siblings */
|
|
|
|
wsi2 = (*w)->mux.sibling_list;
|
2020-02-25 13:28:25 +00:00
|
|
|
assert (wsi2 != *w);
|
2019-12-23 11:31:57 +00:00
|
|
|
(*w)->mux.sibling_list = NULL;
|
|
|
|
(*w)->socket_is_permanently_unusable = 1;
|
2020-12-12 06:21:40 +00:00
|
|
|
__lws_close_free_wsi(*w, (enum lws_close_status)reason, "mux child recurse");
|
2019-12-23 11:31:57 +00:00
|
|
|
*w = wsi2;
|
2020-08-18 13:20:44 +01:00
|
|
|
}
|
2019-12-23 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
lws_wsi_mux_sibling_disconnect(struct lws *wsi)
|
|
|
|
{
|
|
|
|
struct lws *wsi2;
|
|
|
|
|
|
|
|
lws_start_foreach_llp(struct lws **, w,
|
|
|
|
wsi->mux.parent_wsi->mux.child_list) {
|
|
|
|
|
|
|
|
/* disconnect from siblings */
|
|
|
|
if (*w == wsi) {
|
|
|
|
wsi2 = (*w)->mux.sibling_list;
|
|
|
|
(*w)->mux.sibling_list = NULL;
|
|
|
|
*w = wsi2;
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_debug(wsi, " disentangled from sibling %s",
|
2021-06-28 05:05:57 +01:00
|
|
|
lws_wsi_tag(wsi2));
|
2019-12-23 11:31:57 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} lws_end_foreach_llp(w, mux.sibling_list);
|
|
|
|
wsi->mux.parent_wsi->mux.child_count--;
|
2020-02-25 13:28:25 +00:00
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
wsi->mux.parent_wsi = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
lws_wsi_mux_dump_waiting_children(struct lws *wsi)
|
|
|
|
{
|
|
|
|
#if defined(_DEBUG)
|
2020-12-25 05:54:19 +00:00
|
|
|
lwsl_info("%s: %s: children waiting for POLLOUT service:\n",
|
|
|
|
__func__, lws_wsi_tag(wsi));
|
2019-12-23 11:31:57 +00:00
|
|
|
|
|
|
|
wsi = wsi->mux.child_list;
|
|
|
|
while (wsi) {
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_info(wsi, " %c sid %u: 0x%x %s %s",
|
2019-12-23 11:31:57 +00:00
|
|
|
wsi->mux.requested_POLLOUT ? '*' : ' ',
|
2021-06-18 07:28:23 +01:00
|
|
|
wsi->mux.my_sid, lwsi_state(wsi),
|
2020-02-25 13:28:25 +00:00
|
|
|
wsi->role_ops->name,
|
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 ? wsi->a.protocol->name : "noprotocol");
|
2019-12-23 11:31:57 +00:00
|
|
|
|
|
|
|
wsi = wsi->mux.sibling_list;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
lws_wsi_mux_mark_parents_needing_writeable(struct lws *wsi)
|
|
|
|
{
|
2020-03-06 07:25:00 +00:00
|
|
|
struct lws /* *network_wsi = lws_get_network_wsi(wsi), */ *wsi2;
|
|
|
|
//int already = network_wsi->mux.requested_POLLOUT;
|
2019-12-23 11:31:57 +00:00
|
|
|
|
|
|
|
/* mark everybody above him as requesting pollout */
|
|
|
|
|
|
|
|
wsi2 = wsi;
|
|
|
|
while (wsi2) {
|
|
|
|
wsi2->mux.requested_POLLOUT = 1;
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_info(wsi2, "sid %u, pending writable",
|
|
|
|
wsi2->mux.my_sid);
|
2019-12-23 11:31:57 +00:00
|
|
|
wsi2 = wsi2->mux.parent_wsi;
|
|
|
|
}
|
|
|
|
|
2020-03-06 07:25:00 +00:00
|
|
|
return 0; // already;
|
2019-12-23 11:31:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct lws *
|
|
|
|
lws_wsi_mux_move_child_to_tail(struct lws **wsi2)
|
|
|
|
{
|
|
|
|
struct lws *w = *wsi2;
|
|
|
|
|
|
|
|
while (w) {
|
|
|
|
if (!w->mux.sibling_list) { /* w is the current last */
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_debug(w, "*wsi2 = %s\n", lws_wsi_tag(*wsi2));
|
2019-12-23 11:31:57 +00:00
|
|
|
|
|
|
|
if (w == *wsi2) /* we are already last */
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* last points to us as new last */
|
|
|
|
w->mux.sibling_list = *wsi2;
|
|
|
|
|
|
|
|
/* guy pointing to us until now points to
|
|
|
|
* our old next */
|
|
|
|
*wsi2 = (*wsi2)->mux.sibling_list;
|
|
|
|
|
|
|
|
/* we point to nothing because we are last */
|
|
|
|
w->mux.sibling_list->mux.sibling_list = NULL;
|
|
|
|
|
|
|
|
/* w becomes us */
|
|
|
|
w = w->mux.sibling_list;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
w = w->mux.sibling_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* clear the waiting for POLLOUT on the guy that was chosen */
|
|
|
|
|
|
|
|
if (w)
|
|
|
|
w->mux.requested_POLLOUT = 0;
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
lws_wsi_mux_action_pending_writeable_reqs(struct lws *wsi)
|
|
|
|
{
|
|
|
|
struct lws *w = wsi->mux.child_list;
|
|
|
|
|
|
|
|
while (w) {
|
|
|
|
if (w->mux.requested_POLLOUT) {
|
|
|
|
if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
|
|
|
|
return -1;
|
2020-02-25 13:28:25 +00:00
|
|
|
return 0;
|
2019-12-23 11:31:57 +00:00
|
|
|
}
|
|
|
|
w = w->mux.sibling_list;
|
|
|
|
}
|
|
|
|
|
2020-02-25 13:28:25 +00:00
|
|
|
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
|
|
|
|
return -1;
|
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-12-26 02:35:41 +00:00
|
|
|
int
|
|
|
|
lws_wsi_txc_check_skint(struct lws_tx_credit *txc, int32_t tx_cr)
|
|
|
|
{
|
|
|
|
if (txc->tx_cr <= 0) {
|
|
|
|
/*
|
|
|
|
* If other side is not able to cope with us sending any DATA
|
|
|
|
* so no matter if we have POLLOUT on our side if it's DATA we
|
|
|
|
* want to send.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!txc->skint)
|
|
|
|
lwsl_info("%s: %p: skint (%d)\n", __func__, txc,
|
2020-01-16 07:16:01 +00:00
|
|
|
(int)txc->tx_cr);
|
2019-12-26 02:35:41 +00:00
|
|
|
|
|
|
|
txc->skint = 1;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (txc->skint)
|
2020-01-16 07:16:01 +00:00
|
|
|
lwsl_info("%s: %p: unskint (%d)\n", __func__, txc,
|
|
|
|
(int)txc->tx_cr);
|
2019-12-26 02:35:41 +00:00
|
|
|
|
|
|
|
txc->skint = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(_DEBUG)
|
|
|
|
void
|
|
|
|
lws_wsi_txc_describe(struct lws_tx_credit *txc, const char *at, uint32_t sid)
|
|
|
|
{
|
|
|
|
lwsl_info("%s: %p: %s: sid %d: %speer-to-us: %d, us-to-peer: %d\n",
|
2020-01-16 07:16:01 +00:00
|
|
|
__func__, txc, at, (int)sid, txc->skint ? "SKINT, " : "",
|
|
|
|
(int)txc->peer_tx_cr_est, (int)txc->tx_cr);
|
2019-12-26 02:35:41 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int
|
|
|
|
lws_wsi_tx_credit(struct lws *wsi, char peer_to_us, int add)
|
|
|
|
{
|
roles: compress role ops structs
role ops are usually only sparsely filled, there are currently 20
function pointers but several roles only fill in two. No single
role has more than 14 of the ops. On a 32/64 bit build this part
of the ops struct takes a fixed 80 / 160 bytes then.
First reduce the type of the callback reason part from uint16_t to
uint8_t, this saves 12 bytes unconditionally.
Change to a separate function pointer array with a nybble index
array, it costs 10 bytes for the index and a pointer to the
separate array, for 32-bit the cost is
2 + (4 x ops_used)
and for 64-bit
6 + (8 x ops_used)
for 2 x ops_used it means 32-bit: 10 vs 80 / 64-bit: 22 vs 160
For a typical system with h1 (9), h2 (14), listen (2), netlink (2),
pipe (1), raw_skt (3), ws (12), == 43 ops_used out of 140, it means
the .rodata for this reduced from 32-bit: 560 -> 174 (386 byte
saving) and 64-bit: 1120 -> 350 (770 byte saving)
This doesn't account for the changed function ops calling code, two
ways were tried, a preprocessor macro and explicit functions
For an x86_64 gcc 10 build with most options, release mode,
.text + .rodata
before patch: 553282
accessor macro: 552714 (568 byte saving)
accessor functions: 553674 (392 bytes worse than without patch)
therefore we went with the macros
2020-10-19 13:55:21 +01:00
|
|
|
if (wsi->role_ops && lws_rops_fidx(wsi->role_ops, LWS_ROPS_tx_credit))
|
|
|
|
return lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_tx_credit).
|
|
|
|
tx_credit(wsi, peer_to_us, add);
|
2019-12-26 02:35:41 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Let the protocol know about incoming tx credit window updates if it's
|
|
|
|
* managing the flow control manually (it may want to proxy this information)
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
lws_wsi_txc_report_manual_txcr_in(struct lws *wsi, int32_t bump)
|
|
|
|
{
|
|
|
|
if (!wsi->txc.manual)
|
|
|
|
/*
|
|
|
|
* If we don't care about managing it manually, no need to
|
|
|
|
* report it
|
|
|
|
*/
|
|
|
|
return 0;
|
|
|
|
|
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
|
|
|
return user_callback_handle_rxflow(wsi->a.protocol->callback,
|
2019-12-26 02:35:41 +00:00
|
|
|
wsi, LWS_CALLBACK_WSI_TX_CREDIT_GET,
|
|
|
|
wsi->user_space, NULL, (size_t)bump);
|
|
|
|
}
|
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
#if defined(LWS_WITH_CLIENT)
|
|
|
|
|
|
|
|
int
|
|
|
|
lws_wsi_mux_apply_queue(struct lws *wsi)
|
|
|
|
{
|
|
|
|
/* we have a transaction queue that wants to pipeline */
|
|
|
|
|
2021-04-04 04:06:24 +01:00
|
|
|
lws_context_lock(wsi->a.context, __func__); /* -------------- cx { */
|
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
|
|
|
lws_vhost_lock(wsi->a.vhost);
|
2020-02-25 13:28:25 +00:00
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
|
|
|
|
wsi->dll2_cli_txn_queue_owner.head) {
|
|
|
|
struct lws *w = lws_container_of(d, struct lws,
|
|
|
|
dll2_cli_txn_queue);
|
|
|
|
|
2020-02-25 13:28:25 +00:00
|
|
|
#if defined(LWS_ROLE_H2)
|
2019-12-23 11:31:57 +00:00
|
|
|
if (lwsi_role_http(wsi) &&
|
2020-01-30 13:19:11 +00:00
|
|
|
lwsi_state(w) == LRS_H2_WAITING_TO_SEND_HEADERS) {
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_info(w, "cli pipeq to be h2");
|
2019-12-23 11:31:57 +00:00
|
|
|
|
2020-01-30 13:19:11 +00:00
|
|
|
lwsi_set_state(w, LRS_H1C_ISSUE_HANDSHAKE2);
|
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
/* remove ourselves from client queue */
|
|
|
|
lws_dll2_remove(&w->dll2_cli_txn_queue);
|
|
|
|
|
|
|
|
/* attach ourselves as an h2 stream */
|
|
|
|
lws_wsi_h2_adopt(wsi, w);
|
|
|
|
}
|
2020-02-25 13:28:25 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(LWS_ROLE_MQTT)
|
|
|
|
if (lwsi_role_mqtt(wsi) &&
|
|
|
|
lwsi_state(wsi) == LRS_ESTABLISHED) {
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_info(w, "cli pipeq to be mqtt\n");
|
2020-02-25 13:28:25 +00:00
|
|
|
|
|
|
|
/* remove ourselves from client queue */
|
|
|
|
lws_dll2_remove(&w->dll2_cli_txn_queue);
|
|
|
|
|
|
|
|
/* attach ourselves as an h2 stream */
|
|
|
|
lws_wsi_mqtt_adopt(wsi, w);
|
|
|
|
}
|
|
|
|
#endif
|
2019-12-23 11:31:57 +00:00
|
|
|
|
|
|
|
} lws_end_foreach_dll_safe(d, d1);
|
2020-02-25 13:28:25 +00: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
|
|
|
lws_vhost_unlock(wsi->a.vhost);
|
2021-04-04 04:06:24 +01:00
|
|
|
lws_context_unlock(wsi->a.context); /* } cx -------------- */
|
2019-12-23 11:31:57 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|