2014-04-03 07:42:50 +08:00
|
|
|
/*
|
|
|
|
* libwebsockets - small server side websockets and web server implementation
|
|
|
|
*
|
2020-02-08 18:53:08 +07:00
|
|
|
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
|
2014-04-03 07:42:50 +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:
|
2014-04-03 07:42:50 +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.
|
2014-04-03 07:42:50 +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.
|
2014-04-03 07:42:50 +08:00
|
|
|
*/
|
|
|
|
|
2019-08-15 10:49:52 +01:00
|
|
|
#include "private-lib-core.h"
|
2014-04-03 07:42:50 +08:00
|
|
|
|
2016-01-26 20:56:56 +08:00
|
|
|
int
|
|
|
|
_lws_change_pollfd(struct lws *wsi, int _and, int _or, struct lws_pollargs *pa)
|
|
|
|
{
|
2020-08-27 15:37:14 +01:00
|
|
|
#if !defined(LWS_WITH_EVENT_LIBS)
|
2017-11-12 09:16:46 +08:00
|
|
|
volatile struct lws_context_per_thread *vpt;
|
|
|
|
#endif
|
2016-01-26 20:56:56 +08:00
|
|
|
struct lws_context_per_thread *pt;
|
2016-01-29 21:18:54 +08:00
|
|
|
struct lws_context *context;
|
2019-07-13 12:09:22 -07:00
|
|
|
int ret = 0, pa_events;
|
2016-01-26 20:56:56 +08:00
|
|
|
struct lws_pollfd *pfd;
|
|
|
|
int sampled_tid, tid;
|
|
|
|
|
2018-05-06 07:19:21 +08:00
|
|
|
if (!wsi)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
assert(wsi->position_in_fds_table == LWS_NO_FDS_POS ||
|
|
|
|
wsi->position_in_fds_table >= 0);
|
|
|
|
|
|
|
|
if (wsi->position_in_fds_table == LWS_NO_FDS_POS)
|
2016-01-26 20:56:56 +08:00
|
|
|
return 0;
|
|
|
|
|
2017-11-12 09:16:46 +08:00
|
|
|
if (((volatile struct lws *)wsi)->handling_pollout &&
|
|
|
|
!_and && _or == LWS_POLLOUT) {
|
2017-04-05 08:30:55 +08:00
|
|
|
/*
|
|
|
|
* Happening alongside service thread handling POLLOUT.
|
|
|
|
* The danger is when he is finished, he will disable POLLOUT,
|
|
|
|
* countermanding what we changed here.
|
|
|
|
*
|
|
|
|
* Instead of changing the fds, inform the service thread
|
|
|
|
* what happened, and ask it to leave POLLOUT active on exit
|
|
|
|
*/
|
2017-11-12 09:16:46 +08:00
|
|
|
((volatile struct lws *)wsi)->leave_pollout_active = 1;
|
2017-04-05 08:30:55 +08:00
|
|
|
/*
|
|
|
|
* by definition service thread is not in poll wait, so no need
|
|
|
|
* to cancel service
|
|
|
|
*/
|
|
|
|
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_debug(wsi, "using leave_pollout_active");
|
2017-04-05 08:30:55 +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
|
|
|
context = wsi->a.context;
|
2016-01-26 20:56:56 +08:00
|
|
|
pt = &context->pt[(int)wsi->tsi];
|
2017-11-12 09:16:46 +08:00
|
|
|
|
2020-08-27 15:37:14 +01:00
|
|
|
#if !defined(LWS_WITH_EVENT_LIBS)
|
2017-11-12 09:16:46 +08:00
|
|
|
/*
|
|
|
|
* This only applies when we use the default poll() event loop.
|
|
|
|
*
|
|
|
|
* BSD can revert pa->events at any time, when the kernel decides to
|
|
|
|
* exit from poll(). We can't protect against it using locking.
|
|
|
|
*
|
|
|
|
* Therefore we must check first if the service thread is in poll()
|
|
|
|
* wait; if so, we know we must be being called from a foreign thread,
|
|
|
|
* and we must keep a strictly ordered list of changes we made instead
|
|
|
|
* of trying to apply them, since when poll() exits, which may happen
|
|
|
|
* at any time it would revert our changes.
|
|
|
|
*
|
|
|
|
* The plat code will apply them when it leaves the poll() wait
|
|
|
|
* before doing anything else.
|
|
|
|
*/
|
|
|
|
|
|
|
|
vpt = (volatile struct lws_context_per_thread *)pt;
|
|
|
|
|
|
|
|
vpt->foreign_spinlock = 1;
|
|
|
|
lws_memory_barrier();
|
|
|
|
|
|
|
|
if (vpt->inside_poll) {
|
|
|
|
struct lws_foreign_thread_pollfd *ftp, **ftp1;
|
|
|
|
/*
|
|
|
|
* We are certainly a foreign thread trying to change events
|
|
|
|
* while the service thread is in the poll() wait.
|
|
|
|
*
|
|
|
|
* Create a list of changes to be applied after poll() exit,
|
|
|
|
* instead of trying to apply them now.
|
|
|
|
*/
|
|
|
|
ftp = lws_malloc(sizeof(*ftp), "ftp");
|
|
|
|
if (!ftp) {
|
|
|
|
vpt->foreign_spinlock = 0;
|
|
|
|
lws_memory_barrier();
|
|
|
|
ret = -1;
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
|
|
|
|
ftp->_and = _and;
|
|
|
|
ftp->_or = _or;
|
|
|
|
ftp->next = NULL;
|
|
|
|
|
2019-02-23 15:24:57 +08:00
|
|
|
lws_pt_lock(pt, __func__);
|
2024-04-13 12:28:05 +08:00
|
|
|
assert(wsi->position_in_fds_table < (int)pt->fds_count);
|
|
|
|
ftp->fd_index = wsi->position_in_fds_table;
|
2019-02-23 15:24:57 +08:00
|
|
|
|
2017-11-12 09:16:46 +08:00
|
|
|
/* place at END of list to maintain order */
|
|
|
|
ftp1 = (struct lws_foreign_thread_pollfd **)
|
|
|
|
&vpt->foreign_pfd_list;
|
|
|
|
while (*ftp1)
|
|
|
|
ftp1 = &((*ftp1)->next);
|
|
|
|
|
|
|
|
*ftp1 = ftp;
|
|
|
|
vpt->foreign_spinlock = 0;
|
|
|
|
lws_memory_barrier();
|
2019-02-23 15:24:57 +08:00
|
|
|
|
|
|
|
lws_pt_unlock(pt);
|
|
|
|
|
2017-11-12 09:16:46 +08:00
|
|
|
lws_cancel_service_pt(wsi);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
vpt->foreign_spinlock = 0;
|
|
|
|
lws_memory_barrier();
|
|
|
|
#endif
|
|
|
|
|
2020-12-05 05:01:55 +00:00
|
|
|
#if !defined(__linux__) && !defined(WIN32)
|
|
|
|
/* OSX couldn't see close on stdin pipe side otherwise; WSAPOLL
|
|
|
|
* blows up if we give it POLLHUP
|
|
|
|
*/
|
2020-02-12 10:12:39 +00:00
|
|
|
_or |= LWS_POLLHUP;
|
|
|
|
#endif
|
2024-04-13 12:28:05 +08:00
|
|
|
lws_pt_lock(pt, __func__);
|
|
|
|
assert(wsi->position_in_fds_table < (int)pt->fds_count);
|
2016-01-26 20:56:56 +08:00
|
|
|
pfd = &pt->fds[wsi->position_in_fds_table];
|
|
|
|
pa->prev_events = pfd->events;
|
2020-12-12 06:21:40 +00:00
|
|
|
pa->events = pfd->events = (short)((pfd->events & ~_and) | _or);
|
2024-04-13 12:28:05 +08:00
|
|
|
lws_pt_unlock(pt);
|
|
|
|
|
|
|
|
pa->fd = wsi->desc.sockfd;
|
|
|
|
lwsl_wsi_debug(wsi, "fd %d events %d -> %d", pa->fd, pa->prev_events,
|
|
|
|
pa->events);
|
2016-01-26 20:56:56 +08:00
|
|
|
|
2019-12-23 11:31:57 +00:00
|
|
|
if (wsi->mux_substream)
|
2016-04-10 09:33:54 +08:00
|
|
|
return 0;
|
|
|
|
|
2019-08-10 09:33:07 +01:00
|
|
|
#if defined(LWS_WITH_EXTERNAL_POLL)
|
|
|
|
|
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 &&
|
|
|
|
wsi->a.vhost->protocols[0].callback(wsi,
|
2017-10-28 07:42:44 +08:00
|
|
|
LWS_CALLBACK_CHANGE_MODE_POLL_FD,
|
|
|
|
wsi->user_space, (void *)pa, 0)) {
|
2016-01-26 20:56:56 +08:00
|
|
|
ret = -1;
|
|
|
|
goto bail;
|
|
|
|
}
|
2019-08-10 09:33:07 +01:00
|
|
|
#endif
|
2016-01-26 20:56:56 +08:00
|
|
|
|
2018-04-29 10:44:36 +08:00
|
|
|
if (context->event_loop_ops->io) {
|
|
|
|
if (_and & LWS_POLLIN)
|
|
|
|
context->event_loop_ops->io(wsi,
|
|
|
|
LWS_EV_STOP | LWS_EV_READ);
|
|
|
|
|
|
|
|
if (_or & LWS_POLLIN)
|
|
|
|
context->event_loop_ops->io(wsi,
|
|
|
|
LWS_EV_START | LWS_EV_READ);
|
|
|
|
|
|
|
|
if (_and & LWS_POLLOUT)
|
|
|
|
context->event_loop_ops->io(wsi,
|
|
|
|
LWS_EV_STOP | LWS_EV_WRITE);
|
|
|
|
|
|
|
|
if (_or & LWS_POLLOUT)
|
|
|
|
context->event_loop_ops->io(wsi,
|
|
|
|
LWS_EV_START | LWS_EV_WRITE);
|
2016-02-14 09:27:41 +08:00
|
|
|
}
|
|
|
|
|
2016-01-26 20:56:56 +08:00
|
|
|
/*
|
|
|
|
* if we changed something in this pollfd...
|
|
|
|
* ... and we're running in a different thread context
|
|
|
|
* than the service thread...
|
|
|
|
* ... and the service thread is waiting ...
|
|
|
|
* then cancel it to force a restart with our changed events
|
|
|
|
*/
|
|
|
|
pa_events = pa->prev_events != pa->events;
|
2020-12-05 05:01:55 +00:00
|
|
|
pfd->events = (short)pa->events;
|
2016-04-10 09:33:54 +08:00
|
|
|
|
2016-01-26 20:56:56 +08:00
|
|
|
if (pa_events) {
|
|
|
|
if (lws_plat_change_pollfd(context, wsi, pfd)) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_info(wsi, "failed");
|
2016-01-26 20:56:56 +08:00
|
|
|
ret = -1;
|
|
|
|
goto bail;
|
|
|
|
}
|
2018-07-25 16:26:41 +08:00
|
|
|
sampled_tid = pt->service_tid;
|
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 (sampled_tid && wsi->a.vhost) {
|
|
|
|
tid = wsi->a.vhost->protocols[0].callback(wsi,
|
2016-01-26 20:56:56 +08:00
|
|
|
LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
|
|
|
|
if (tid == -1) {
|
|
|
|
ret = -1;
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
if (tid != sampled_tid)
|
|
|
|
lws_cancel_service_pt(wsi);
|
|
|
|
}
|
|
|
|
}
|
2017-11-12 09:16:46 +08:00
|
|
|
|
2016-01-26 20:56:56 +08:00
|
|
|
bail:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-08-18 05:04:15 +01:00
|
|
|
#if defined(LWS_WITH_SERVER)
|
2018-03-08 12:04:13 +08:00
|
|
|
/*
|
|
|
|
* Enable or disable listen sockets on this pt globally...
|
|
|
|
* it's modulated according to the pt having space for a new accept.
|
|
|
|
*/
|
context deprecation
1) This makes lwsws run a parent process with the original permissions.
But this process is only able to respond to SIGHUP, it doesn't do anything
else.
2) You can send this parent process a SIGHUP now to cause it to
- close listening sockets in existing lwsws processes
- mark those processes as to exit when the number of active connections
on the falls to zero
- spawn a fresh child process from scratch, using latest configuration
file content, latest plugins, etc. It can now reopen listening sockets
if it chooses to, or open different listen ports or whatever.
Notes:
1) lws_context_destroy() has been split into two pieces... the reason for
the split is the first part closes the per-vhost protocols, but since
they may have created libuv objects in the per-vhost protocol storage,
these cannot be freed until after the loop has been run.
That's the purpose of the second part of the context destruction,
lws_context_destroy2().
For compatibility, if you are not using libuv, the first part calls the
second part. However if you are using libuv, you must now call the
second part from your own main.c after the first part.
2016-12-16 07:37:43 +08:00
|
|
|
static void
|
2018-03-08 12:04:13 +08:00
|
|
|
lws_accept_modulation(struct lws_context *context,
|
|
|
|
struct lws_context_per_thread *pt, int allow)
|
context deprecation
1) This makes lwsws run a parent process with the original permissions.
But this process is only able to respond to SIGHUP, it doesn't do anything
else.
2) You can send this parent process a SIGHUP now to cause it to
- close listening sockets in existing lwsws processes
- mark those processes as to exit when the number of active connections
on the falls to zero
- spawn a fresh child process from scratch, using latest configuration
file content, latest plugins, etc. It can now reopen listening sockets
if it chooses to, or open different listen ports or whatever.
Notes:
1) lws_context_destroy() has been split into two pieces... the reason for
the split is the first part closes the per-vhost protocols, but since
they may have created libuv objects in the per-vhost protocol storage,
these cannot be freed until after the loop has been run.
That's the purpose of the second part of the context destruction,
lws_context_destroy2().
For compatibility, if you are not using libuv, the first part calls the
second part. However if you are using libuv, you must now call the
second part from your own main.c after the first part.
2016-12-16 07:37:43 +08:00
|
|
|
{
|
|
|
|
struct lws_vhost *vh = context->vhost_list;
|
|
|
|
struct lws_pollargs pa1;
|
|
|
|
|
|
|
|
while (vh) {
|
2021-06-21 08:50:13 +01:00
|
|
|
lws_start_foreach_dll(struct lws_dll2 *, d,
|
|
|
|
lws_dll2_get_head(&vh->listen_wsi)) {
|
|
|
|
struct lws *wsi = lws_container_of(d, struct lws,
|
|
|
|
listen_list);
|
|
|
|
|
|
|
|
_lws_change_pollfd(wsi, allow ? 0 : LWS_POLLIN,
|
|
|
|
allow ? LWS_POLLIN : 0, &pa1);
|
|
|
|
} lws_end_foreach_dll(d);
|
|
|
|
|
context deprecation
1) This makes lwsws run a parent process with the original permissions.
But this process is only able to respond to SIGHUP, it doesn't do anything
else.
2) You can send this parent process a SIGHUP now to cause it to
- close listening sockets in existing lwsws processes
- mark those processes as to exit when the number of active connections
on the falls to zero
- spawn a fresh child process from scratch, using latest configuration
file content, latest plugins, etc. It can now reopen listening sockets
if it chooses to, or open different listen ports or whatever.
Notes:
1) lws_context_destroy() has been split into two pieces... the reason for
the split is the first part closes the per-vhost protocols, but since
they may have created libuv objects in the per-vhost protocol storage,
these cannot be freed until after the loop has been run.
That's the purpose of the second part of the context destruction,
lws_context_destroy2().
For compatibility, if you are not using libuv, the first part calls the
second part. However if you are using libuv, you must now call the
second part from your own main.c after the first part.
2016-12-16 07:37:43 +08:00
|
|
|
vh = vh->vhost_next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-04-22 06:32:15 +01:00
|
|
|
#if _LWS_ENABLED_LOGS & LLL_WARN
|
2019-08-09 10:12:09 +01:00
|
|
|
void
|
|
|
|
__dump_fds(struct lws_context_per_thread *pt, const char *s)
|
|
|
|
{
|
|
|
|
unsigned int n;
|
|
|
|
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_cx_warn(pt->context, "fds_count %u, %s", pt->fds_count, s);
|
2019-08-09 10:12:09 +01:00
|
|
|
|
|
|
|
for (n = 0; n < pt->fds_count; n++) {
|
|
|
|
struct lws *wsi = wsi_from_fd(pt->context, pt->fds[n].fd);
|
|
|
|
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_cx_warn(pt->context, " %d: fd %d, wsi %s, pos_in_fds: %d",
|
2020-12-25 05:54:19 +00:00
|
|
|
n + 1, pt->fds[n].fd, lws_wsi_tag(wsi),
|
2019-08-09 10:12:09 +01:00
|
|
|
wsi ? wsi->position_in_fds_table : -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define __dump_fds(x, y)
|
|
|
|
#endif
|
|
|
|
|
2014-04-03 07:42:50 +08:00
|
|
|
int
|
2018-03-05 16:49:28 +08:00
|
|
|
__insert_wsi_socket_into_fds(struct lws_context *context, struct lws *wsi)
|
2014-04-03 07:42:50 +08:00
|
|
|
{
|
2019-08-10 09:33:07 +01:00
|
|
|
#if defined(LWS_WITH_EXTERNAL_POLL)
|
2017-02-27 12:55:56 +08:00
|
|
|
struct lws_pollargs pa = { wsi->desc.sockfd, LWS_POLLIN, 0 };
|
2019-08-10 09:33:07 +01:00
|
|
|
#endif
|
2016-01-19 03:34:24 +08:00
|
|
|
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
|
2016-01-26 20:56:56 +08:00
|
|
|
int ret = 0;
|
context deprecation
1) This makes lwsws run a parent process with the original permissions.
But this process is only able to respond to SIGHUP, it doesn't do anything
else.
2) You can send this parent process a SIGHUP now to cause it to
- close listening sockets in existing lwsws processes
- mark those processes as to exit when the number of active connections
on the falls to zero
- spawn a fresh child process from scratch, using latest configuration
file content, latest plugins, etc. It can now reopen listening sockets
if it chooses to, or open different listen ports or whatever.
Notes:
1) lws_context_destroy() has been split into two pieces... the reason for
the split is the first part closes the per-vhost protocols, but since
they may have created libuv objects in the per-vhost protocol storage,
these cannot be freed until after the loop has been run.
That's the purpose of the second part of the context destruction,
lws_context_destroy2().
For compatibility, if you are not using libuv, the first part calls the
second part. However if you are using libuv, you must now call the
second part from your own main.c after the first part.
2016-12-16 07:37:43 +08:00
|
|
|
|
2019-08-09 10:12:09 +01:00
|
|
|
// __dump_fds(pt, "pre insert");
|
2016-01-26 20:56:56 +08:00
|
|
|
|
2020-08-31 08:12:16 +01:00
|
|
|
lws_pt_assert_lock_held(pt);
|
|
|
|
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_wsi_debug(wsi, "tsi=%d, sock=%d, pos-in-fds=%d",
|
|
|
|
wsi->tsi, wsi->desc.sockfd, pt->fds_count);
|
2014-04-03 07:42:50 +08:00
|
|
|
|
2016-01-19 03:34:24 +08:00
|
|
|
if ((unsigned int)pt->fds_count >= context->fd_limit_per_thread) {
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_cx_err(context, "Too many fds (%d vs %d)", context->max_fds,
|
|
|
|
context->fd_limit_per_thread);
|
2014-04-03 07:42:50 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-11-30 12:40:46 +08:00
|
|
|
#if !defined(_WIN32)
|
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->max_fds_unrelated_to_ulimit &&
|
2020-12-12 06:21:40 +00:00
|
|
|
wsi->desc.sockfd - lws_plat_socket_offset() >= (int)context->max_fds) {
|
2021-06-18 07:28:23 +01:00
|
|
|
lwsl_cx_err(context, "Socket fd %d is too high (%d) offset %d",
|
2018-11-23 08:47:56 +08:00
|
|
|
wsi->desc.sockfd, context->max_fds,
|
|
|
|
lws_plat_socket_offset());
|
2014-04-03 07:42:50 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2015-01-30 10:13:01 +08:00
|
|
|
#endif
|
2014-04-03 07:42:50 +08:00
|
|
|
|
|
|
|
assert(wsi);
|
2020-10-04 07:28:41 +01:00
|
|
|
|
|
|
|
#if defined(LWS_WITH_NETLINK)
|
2021-03-07 09:44:29 +00:00
|
|
|
assert(wsi->event_pipe || wsi->a.vhost || wsi == pt->context->netlink);
|
2020-10-04 07:28:41 +01:00
|
|
|
#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
|
|
|
assert(wsi->event_pipe || wsi->a.vhost);
|
2020-10-04 07:28:41 +01:00
|
|
|
#endif
|
2017-02-27 12:55:56 +08:00
|
|
|
assert(lws_socket_is_valid(wsi->desc.sockfd));
|
2014-04-03 07:42:50 +08:00
|
|
|
|
2019-08-10 09:33:07 +01:00
|
|
|
#if defined(LWS_WITH_EXTERNAL_POLL)
|
|
|
|
|
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 &&
|
|
|
|
wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_LOCK_POLL,
|
2015-12-17 07:54:44 +08:00
|
|
|
wsi->user_space, (void *) &pa, 1))
|
2015-10-15 07:39:33 +08:00
|
|
|
return -1;
|
2019-08-10 09:33:07 +01:00
|
|
|
#endif
|
2014-04-03 07:42:50 +08:00
|
|
|
|
unix plat: add minimal wsi fd map option
An lws context usually contains a processwide fd -> wsi lookup table.
This allows any possible fd returned by a *nix type OS to be immediately
converted to a wsi just by indexing an array of struct lws * the size of
the highest possible fd, as found by ulimit -n or similar.
This works modestly for Linux type systems where the default ulimit -n for
a process is 1024, it means a 4KB or 8KB lookup table for 32-bit or
64-bit systems.
However in the case your lws usage is much simpler, like one outgoing
client connection and no serving, this represents increasing waste. It's
made much worse if the system has a much larger default ulimit -n, eg 1M,
the table is occupying 4MB or 8MB, of which you will only use one.
Even so, because lws can't be sure the OS won't return a socket fd at any
number up to (ulimit -n - 1), it has to allocate the whole lookup table
at the moment.
This patch looks to see if the context creation info is setting
info->fd_limit_per_thread... if it leaves it at the default 0, then
everything is as it was before this patch. However if finds that
(info->fd_limit_per_thread * actual_number_of_service_threads) where
the default number of service threads is 1, is less than the fd limit
set by ulimit -n, lws switches to a slower lookup table scheme, which
only allocates the requested number of slots. Lookups happen then by
iterating the table and comparing rather than indexing the array
directly, which is obviously somewhat of a performance hit.
However in the case where you know lws will only have a very few wsi
maximum, this method can very usefully trade off speed to be able to
avoid the allocation sized by ulimit -n.
minimal examples for client that can make use of this are also modified
by this patch to use the smaller context allocations.
2019-05-17 01:20:07 +01:00
|
|
|
if (insert_wsi(context, wsi))
|
|
|
|
return -1;
|
2016-01-26 20:56:56 +08:00
|
|
|
pt->count_conns++;
|
2020-12-12 06:21:40 +00:00
|
|
|
wsi->position_in_fds_table = (int)pt->fds_count;
|
2016-08-07 08:33:08 +08:00
|
|
|
|
2017-02-27 12:55:56 +08:00
|
|
|
pt->fds[wsi->position_in_fds_table].fd = wsi->desc.sockfd;
|
2016-07-23 14:18:25 +08:00
|
|
|
pt->fds[wsi->position_in_fds_table].events = LWS_POLLIN;
|
2019-08-10 09:33:07 +01:00
|
|
|
#if defined(LWS_WITH_EXTERNAL_POLL)
|
2016-01-26 20:56:56 +08:00
|
|
|
pa.events = pt->fds[pt->fds_count].events;
|
2019-08-10 09:33:07 +01:00
|
|
|
#endif
|
2016-01-26 20:56:56 +08:00
|
|
|
|
2014-04-03 07:42:50 +08:00
|
|
|
lws_plat_insert_socket_into_fds(context, wsi);
|
|
|
|
|
2019-08-10 09:33:07 +01:00
|
|
|
#if defined(LWS_WITH_EXTERNAL_POLL)
|
|
|
|
|
2014-04-03 07:42:50 +08:00
|
|
|
/* external POLL support via protocol 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
|
|
|
if (wsi->a.vhost &&
|
|
|
|
wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_ADD_POLL_FD,
|
2015-12-17 07:54:44 +08:00
|
|
|
wsi->user_space, (void *) &pa, 0))
|
2016-01-26 20:56:56 +08:00
|
|
|
ret = -1;
|
2019-08-10 09:33:07 +01:00
|
|
|
#endif
|
2019-08-18 05:04:15 +01:00
|
|
|
#if defined(LWS_WITH_SERVER)
|
|
|
|
/* if no more room, defeat accepts on this service thread */
|
2016-01-26 20:56:56 +08:00
|
|
|
if ((unsigned int)pt->fds_count == context->fd_limit_per_thread - 1)
|
2018-03-08 12:04:13 +08:00
|
|
|
lws_accept_modulation(context, pt, 0);
|
2016-01-26 20:56:56 +08:00
|
|
|
#endif
|
2014-04-03 07:42:50 +08:00
|
|
|
|
2019-08-10 09:33:07 +01:00
|
|
|
#if defined(LWS_WITH_EXTERNAL_POLL)
|
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 &&
|
|
|
|
wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_UNLOCK_POLL,
|
2015-12-17 07:54:44 +08:00
|
|
|
wsi->user_space, (void *)&pa, 1))
|
2016-01-26 20:56:56 +08:00
|
|
|
ret = -1;
|
2019-08-10 09:33:07 +01:00
|
|
|
#endif
|
2014-04-03 07:42:50 +08:00
|
|
|
|
2019-08-09 10:12:09 +01:00
|
|
|
// __dump_fds(pt, "post insert");
|
|
|
|
|
2016-01-26 20:56:56 +08:00
|
|
|
return ret;
|
2014-04-03 07:42:50 +08:00
|
|
|
}
|
|
|
|
|
2021-04-09 15:23:06 +01:00
|
|
|
/* requires pt lock */
|
|
|
|
|
2014-04-03 07:42:50 +08:00
|
|
|
int
|
2018-03-05 16:49:28 +08:00
|
|
|
__remove_wsi_socket_from_fds(struct lws *wsi)
|
2014-04-03 07:42:50 +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
|
|
|
struct lws_context *context = wsi->a.context;
|
2019-08-10 09:33:07 +01:00
|
|
|
#if defined(LWS_WITH_EXTERNAL_POLL)
|
2017-02-27 12:55:56 +08:00
|
|
|
struct lws_pollargs pa = { wsi->desc.sockfd, 0, 0 };
|
2019-08-10 09:33:07 +01:00
|
|
|
#endif
|
2016-01-19 03:34:24 +08:00
|
|
|
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
|
2016-01-29 21:18:54 +08:00
|
|
|
struct lws *end_wsi;
|
2019-08-01 18:31:11 +01:00
|
|
|
int v, m, ret = 0;
|
2014-04-03 07:42:50 +08:00
|
|
|
|
2020-08-31 08:12:16 +01:00
|
|
|
lws_pt_assert_lock_held(pt);
|
|
|
|
|
2019-08-09 10:12:09 +01:00
|
|
|
// __dump_fds(pt, "pre remove");
|
|
|
|
|
2017-11-30 12:40:46 +08:00
|
|
|
#if !defined(_WIN32)
|
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->max_fds_unrelated_to_ulimit &&
|
2020-12-12 06:21:40 +00:00
|
|
|
wsi->desc.sockfd - lws_plat_socket_offset() > (int)context->max_fds) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_err(wsi, "fd %d too high (%d)",
|
|
|
|
wsi->desc.sockfd,
|
|
|
|
context->max_fds);
|
2019-08-01 18:31:11 +01:00
|
|
|
|
2014-04-03 07:42:50 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2015-10-13 19:54:57 -05:00
|
|
|
#endif
|
2019-08-10 09:33:07 +01:00
|
|
|
#if defined(LWS_WITH_EXTERNAL_POLL)
|
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 && wsi->a.vhost->protocols &&
|
|
|
|
wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_LOCK_POLL,
|
2015-12-17 07:54:44 +08:00
|
|
|
wsi->user_space, (void *)&pa, 1))
|
2015-10-15 07:39:33 +08:00
|
|
|
return -1;
|
2019-08-10 09:33:07 +01:00
|
|
|
#endif
|
2014-04-03 07:42:50 +08:00
|
|
|
|
2020-04-15 20:57:00 +01:00
|
|
|
__lws_same_vh_protocol_remove(wsi);
|
context deprecation
1) This makes lwsws run a parent process with the original permissions.
But this process is only able to respond to SIGHUP, it doesn't do anything
else.
2) You can send this parent process a SIGHUP now to cause it to
- close listening sockets in existing lwsws processes
- mark those processes as to exit when the number of active connections
on the falls to zero
- spawn a fresh child process from scratch, using latest configuration
file content, latest plugins, etc. It can now reopen listening sockets
if it chooses to, or open different listen ports or whatever.
Notes:
1) lws_context_destroy() has been split into two pieces... the reason for
the split is the first part closes the per-vhost protocols, but since
they may have created libuv objects in the per-vhost protocol storage,
these cannot be freed until after the loop has been run.
That's the purpose of the second part of the context destruction,
lws_context_destroy2().
For compatibility, if you are not using libuv, the first part calls the
second part. However if you are using libuv, you must now call the
second part from your own main.c after the first part.
2016-12-16 07:37:43 +08:00
|
|
|
|
2016-07-23 14:18:25 +08:00
|
|
|
/* the guy who is to be deleted's slot index in pt->fds */
|
|
|
|
m = wsi->position_in_fds_table;
|
|
|
|
|
2018-05-06 07:19:21 +08:00
|
|
|
/* these are the only valid possibilities for position_in_fds_table */
|
2020-05-04 07:24:58 +01:00
|
|
|
assert(m == LWS_NO_FDS_POS || (m >= 0 && (unsigned int)m < pt->fds_count));
|
2018-05-06 07:19:21 +08:00
|
|
|
|
2018-04-29 10:44:36 +08:00
|
|
|
if (context->event_loop_ops->io)
|
2021-08-21 17:43:55 +01:00
|
|
|
context->event_loop_ops->io(wsi, LWS_EV_STOP | LWS_EV_READ |
|
|
|
|
LWS_EV_WRITE);
|
2019-08-09 10:12:09 +01:00
|
|
|
/*
|
2020-12-25 05:54:19 +00:00
|
|
|
lwsl_notice("%s: wsi=%s, skt=%d, fds pos=%d, end guy pos=%d, endfd=%d\n",
|
|
|
|
__func__, lws_wsi_tag(wsi), wsi->desc.sockfd, wsi->position_in_fds_table,
|
2019-08-01 18:31:11 +01:00
|
|
|
pt->fds_count, pt->fds[pt->fds_count - 1].fd); */
|
2016-01-26 20:56:56 +08:00
|
|
|
|
2018-05-06 07:19:21 +08:00
|
|
|
if (m != LWS_NO_FDS_POS) {
|
2019-08-01 18:31:11 +01:00
|
|
|
char fixup = 0;
|
2018-04-27 09:13:23 +08:00
|
|
|
|
2019-08-01 18:31:11 +01:00
|
|
|
assert(pt->fds_count && (unsigned int)m != pt->fds_count);
|
2018-04-27 09:13:23 +08:00
|
|
|
|
|
|
|
/* deletion guy's lws_lookup entry needs nuking */
|
|
|
|
delete_from_fd(context, wsi->desc.sockfd);
|
2018-05-06 07:19:21 +08:00
|
|
|
|
2019-08-01 18:31:11 +01:00
|
|
|
if ((unsigned int)m != pt->fds_count - 1) {
|
|
|
|
/* have the last guy take up the now vacant slot */
|
|
|
|
pt->fds[m] = pt->fds[pt->fds_count - 1];
|
|
|
|
fixup = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pt->fds[pt->fds_count - 1].fd = -1;
|
|
|
|
|
|
|
|
/* this decrements pt->fds_count */
|
|
|
|
lws_plat_delete_socket_from_fds(context, wsi, m);
|
|
|
|
pt->count_conns--;
|
|
|
|
if (fixup) {
|
|
|
|
v = (int) pt->fds[m].fd;
|
|
|
|
/* old end guy's "position in fds table" is now the
|
|
|
|
* deletion guy's old one */
|
|
|
|
end_wsi = wsi_from_fd(context, v);
|
|
|
|
if (!end_wsi) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_err(wsi, "no wsi for fd %d pos %d, "
|
|
|
|
"pt->fds_count=%d",
|
|
|
|
(int)pt->fds[m].fd, m,
|
|
|
|
pt->fds_count);
|
2020-04-14 19:04:13 +01:00
|
|
|
// assert(0);
|
2019-08-01 18:31:11 +01:00
|
|
|
} else
|
|
|
|
end_wsi->position_in_fds_table = m;
|
|
|
|
}
|
|
|
|
|
2018-04-27 09:13:23 +08:00
|
|
|
/* removed wsi has no position any more */
|
2018-05-06 07:19:21 +08:00
|
|
|
wsi->position_in_fds_table = LWS_NO_FDS_POS;
|
2014-04-03 07:42:50 +08:00
|
|
|
|
2019-08-10 09:33:07 +01:00
|
|
|
#if defined(LWS_WITH_EXTERNAL_POLL)
|
2021-11-22 15:37:18 +00:00
|
|
|
/* remove also from external POLL support via protocol 0 */
|
|
|
|
if (lws_socket_is_valid(wsi->desc.sockfd) && wsi->a.vhost &&
|
|
|
|
wsi->a.vhost->protocols[0].callback(wsi,
|
|
|
|
LWS_CALLBACK_DEL_POLL_FD,
|
|
|
|
wsi->user_space,
|
|
|
|
(void *) &pa, 0))
|
|
|
|
ret = -1;
|
2019-08-10 09:33:07 +01:00
|
|
|
#endif
|
2021-11-22 15:37:18 +00:00
|
|
|
}
|
2017-10-24 11:59:44 +08:00
|
|
|
|
2019-08-18 05:04:15 +01:00
|
|
|
#if defined(LWS_WITH_SERVER)
|
2017-10-24 11:59:44 +08:00
|
|
|
if (!context->being_destroyed &&
|
|
|
|
/* if this made some room, accept connects on this thread */
|
|
|
|
(unsigned int)pt->fds_count < context->fd_limit_per_thread - 1)
|
2018-03-08 12:04:13 +08:00
|
|
|
lws_accept_modulation(context, pt, 1);
|
2016-01-26 20:56:56 +08:00
|
|
|
#endif
|
|
|
|
|
2019-08-10 09:33:07 +01:00
|
|
|
#if defined(LWS_WITH_EXTERNAL_POLL)
|
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 &&
|
|
|
|
wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_UNLOCK_POLL,
|
2017-09-23 12:55:21 +08:00
|
|
|
wsi->user_space, (void *) &pa, 1))
|
2016-01-26 20:56:56 +08:00
|
|
|
ret = -1;
|
2019-08-10 09:33:07 +01:00
|
|
|
#endif
|
2017-11-30 12:40:46 +08:00
|
|
|
|
2019-08-09 10:12:09 +01:00
|
|
|
// __dump_fds(pt, "post remove");
|
|
|
|
|
2016-01-26 20:56:56 +08:00
|
|
|
return ret;
|
2014-04-03 07:42:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-03-02 14:22:49 +08:00
|
|
|
__lws_change_pollfd(struct lws *wsi, int _and, int _or)
|
2014-04-03 07:42:50 +08:00
|
|
|
{
|
2016-01-29 21:18:54 +08:00
|
|
|
struct lws_context *context;
|
2015-12-04 11:08:32 +08:00
|
|
|
struct lws_pollargs pa;
|
2016-01-29 21:18:54 +08:00
|
|
|
int ret = 0;
|
2014-04-03 07:42:50 +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 || (!wsi->a.protocol && !wsi->event_pipe) ||
|
2018-05-06 07:19:21 +08:00
|
|
|
wsi->position_in_fds_table == LWS_NO_FDS_POS)
|
2018-04-13 16:01:38 +08:00
|
|
|
return 0;
|
2015-12-14 08:52:03 +08:00
|
|
|
|
2015-12-17 18:25:25 +08:00
|
|
|
context = lws_get_context(wsi);
|
2014-12-15 15:08:13 +08:00
|
|
|
if (!context)
|
|
|
|
return 1;
|
|
|
|
|
2019-08-10 09:33:07 +01:00
|
|
|
#if defined(LWS_WITH_EXTERNAL_POLL)
|
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 &&
|
|
|
|
wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_LOCK_POLL,
|
2017-10-28 07:42:44 +08:00
|
|
|
wsi->user_space, (void *) &pa, 0))
|
2015-10-15 07:39:33 +08:00
|
|
|
return -1;
|
2019-08-10 09:33:07 +01:00
|
|
|
#endif
|
2014-04-03 07:42:50 +08:00
|
|
|
|
2016-01-26 20:56:56 +08:00
|
|
|
ret = _lws_change_pollfd(wsi, _and, _or, &pa);
|
2019-08-10 09:33:07 +01:00
|
|
|
|
|
|
|
#if defined(LWS_WITH_EXTERNAL_POLL)
|
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 &&
|
|
|
|
wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_UNLOCK_POLL,
|
2015-12-17 07:54:44 +08:00
|
|
|
wsi->user_space, (void *) &pa, 0))
|
2016-01-26 20:56:56 +08:00
|
|
|
ret = -1;
|
2019-08-10 09:33:07 +01:00
|
|
|
#endif
|
2015-12-14 08:52:03 +08:00
|
|
|
|
2016-01-26 20:56:56 +08:00
|
|
|
return ret;
|
2014-04-03 07:42:50 +08:00
|
|
|
}
|
|
|
|
|
2018-03-02 14:22:49 +08:00
|
|
|
int
|
|
|
|
lws_change_pollfd(struct lws *wsi, int _and, int _or)
|
|
|
|
{
|
|
|
|
struct lws_context_per_thread *pt;
|
|
|
|
int 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
|
|
|
pt = &wsi->a.context->pt[(int)wsi->tsi];
|
2018-03-02 14:22:49 +08:00
|
|
|
|
|
|
|
lws_pt_lock(pt, __func__);
|
|
|
|
ret = __lws_change_pollfd(wsi, _and, _or);
|
|
|
|
lws_pt_unlock(pt);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2015-12-16 18:19:08 +08:00
|
|
|
lws_callback_on_writable(struct lws *wsi)
|
2014-04-03 07:42:50 +08:00
|
|
|
{
|
2020-01-30 13:19:11 +00:00
|
|
|
struct lws *w = wsi;
|
2016-02-24 21:27:46 +08:00
|
|
|
|
2018-04-02 11:55:17 +08:00
|
|
|
if (lwsi_state(wsi) == LRS_SHUTDOWN)
|
2016-02-24 21:27:46 +08:00
|
|
|
return 0;
|
2014-10-22 15:37:28 +08:00
|
|
|
|
2016-04-16 08:40:35 +08:00
|
|
|
if (wsi->socket_is_permanently_unusable)
|
|
|
|
return 0;
|
|
|
|
|
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_callback_on_writable)) {
|
|
|
|
int q = lws_rops_func_fidx(wsi->role_ops,
|
|
|
|
LWS_ROPS_callback_on_writable).
|
|
|
|
callback_on_writable(wsi);
|
2020-02-25 13:28:25 +00:00
|
|
|
if (q)
|
2018-04-11 13:39:42 +08:00
|
|
|
return 1;
|
2020-01-30 13:19:11 +00:00
|
|
|
w = lws_get_network_wsi(wsi);
|
2020-02-25 13:28:25 +00:00
|
|
|
} else
|
|
|
|
if (w->position_in_fds_table == LWS_NO_FDS_POS) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_debug(wsi, "failed to find socket %d",
|
|
|
|
wsi->desc.sockfd);
|
2020-02-25 13:28:25 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-01-30 13:19:11 +00:00
|
|
|
if (__lws_change_pollfd(w, 0, LWS_POLLOUT))
|
2014-04-03 07:42:50 +08:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-03-02 14:22:49 +08:00
|
|
|
|
2017-04-06 13:49:17 +08:00
|
|
|
/*
|
|
|
|
* stitch protocol choice into the vh protocol linked list
|
|
|
|
* We always insert ourselves at the start of the list
|
|
|
|
*
|
|
|
|
* X <-> B
|
|
|
|
* X <-> pAn <-> pB
|
|
|
|
*
|
|
|
|
* Illegal to attach more than once without detach inbetween
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
lws_same_vh_protocol_insert(struct lws *wsi, int n)
|
|
|
|
{
|
2021-04-04 04:06:24 +01:00
|
|
|
lws_context_lock(wsi->a.context, __func__);
|
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);
|
2018-03-02 15:31:35 +08:00
|
|
|
|
2019-08-08 16:58:55 +01:00
|
|
|
lws_dll2_remove(&wsi->same_vh_protocol);
|
|
|
|
lws_dll2_add_head(&wsi->same_vh_protocol,
|
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->same_vh_protocol_owner[n]);
|
2019-03-20 07:39:55 +08:00
|
|
|
|
2020-12-12 06:21:40 +00:00
|
|
|
wsi->bound_vhost_index = (uint8_t)n;
|
2018-03-07 18:15:17 +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
|
|
|
lws_vhost_unlock(wsi->a.vhost);
|
2021-04-04 04:06:24 +01:00
|
|
|
lws_context_unlock(wsi->a.context);
|
2017-04-06 13:49:17 +08:00
|
|
|
}
|
|
|
|
|
2018-10-06 08:00:32 +08:00
|
|
|
void
|
|
|
|
__lws_same_vh_protocol_remove(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 && wsi->a.vhost->same_vh_protocol_owner)
|
2019-08-08 16:58:55 +01:00
|
|
|
lws_dll2_remove(&wsi->same_vh_protocol);
|
2018-10-06 08:00:32 +08:00
|
|
|
}
|
|
|
|
|
2017-04-06 13:49:17 +08:00
|
|
|
void
|
|
|
|
lws_same_vh_protocol_remove(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)
|
2018-03-02 15:31:35 +08:00
|
|
|
return;
|
|
|
|
|
2021-04-04 04:06:24 +01:00
|
|
|
lws_context_lock(wsi->a.context, __func__);
|
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);
|
2018-03-02 15:31:35 +08:00
|
|
|
|
2018-10-06 08:00:32 +08:00
|
|
|
__lws_same_vh_protocol_remove(wsi);
|
2018-03-02 15:31:35 +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
|
|
|
lws_vhost_unlock(wsi->a.vhost);
|
2021-04-04 04:06:24 +01:00
|
|
|
lws_context_unlock(wsi->a.context);
|
2017-04-06 13:49:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2016-04-16 08:40:35 +08:00
|
|
|
lws_callback_on_writable_all_protocol_vhost(const struct lws_vhost *vhost,
|
2018-09-30 07:07:48 +08:00
|
|
|
const struct lws_protocols *protocol)
|
2014-04-03 07:42:50 +08:00
|
|
|
{
|
2016-01-29 21:18:54 +08:00
|
|
|
struct lws *wsi;
|
2018-09-30 07:07:48 +08:00
|
|
|
int n;
|
2016-01-19 03:34:24 +08:00
|
|
|
|
2016-04-16 08:40:35 +08:00
|
|
|
if (protocol < vhost->protocols ||
|
|
|
|
protocol >= (vhost->protocols + vhost->count_protocols)) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_vhost_err((struct lws_vhost *)vhost,
|
|
|
|
"protocol %p is not from vhost %p (%p - %p)",
|
|
|
|
protocol, vhost->protocols, vhost,
|
|
|
|
(vhost->protocols + vhost->count_protocols));
|
2016-04-16 08:40:35 +08:00
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-10-14 11:38:08 +08:00
|
|
|
n = (int)(protocol - vhost->protocols);
|
2017-09-23 12:55:21 +08:00
|
|
|
|
2019-08-08 16:58:55 +01:00
|
|
|
lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
|
|
|
|
lws_dll2_get_head(&vhost->same_vh_protocol_owner[n])) {
|
2018-09-30 07:07:48 +08:00
|
|
|
wsi = lws_container_of(d, struct lws, same_vh_protocol);
|
|
|
|
|
2024-05-11 18:28:04 +08:00
|
|
|
assert(wsi->a.protocol &&
|
|
|
|
wsi->a.protocol->callback == protocol->callback &&
|
|
|
|
!strcmp(protocol->name, wsi->a.protocol->name));
|
|
|
|
|
2016-04-16 08:40:35 +08:00
|
|
|
lws_callback_on_writable(wsi);
|
2018-09-30 07:07:48 +08:00
|
|
|
|
|
|
|
} lws_end_foreach_dll_safe(d, d1);
|
2014-04-03 07:42:50 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2016-04-06 16:15:40 +08:00
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2016-04-16 08:40:35 +08:00
|
|
|
lws_callback_on_writable_all_protocol(const struct lws_context *context,
|
2016-04-06 16:15:40 +08:00
|
|
|
const struct lws_protocols *protocol)
|
|
|
|
{
|
2017-11-10 08:56:44 +08:00
|
|
|
struct lws_vhost *vhost;
|
2016-04-16 08:40:35 +08:00
|
|
|
int n;
|
|
|
|
|
2017-11-10 08:56:44 +08:00
|
|
|
if (!context)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
vhost = context->vhost_list;
|
|
|
|
|
2016-04-16 08:40:35 +08:00
|
|
|
while (vhost) {
|
|
|
|
for (n = 0; n < vhost->count_protocols; n++)
|
|
|
|
if (protocol->callback ==
|
2018-11-23 08:47:56 +08:00
|
|
|
vhost->protocols[n].callback &&
|
2016-04-16 08:40:35 +08:00
|
|
|
!strcmp(protocol->name, vhost->protocols[n].name))
|
|
|
|
break;
|
|
|
|
if (n != vhost->count_protocols)
|
|
|
|
lws_callback_on_writable_all_protocol_vhost(
|
|
|
|
vhost, &vhost->protocols[n]);
|
|
|
|
|
|
|
|
vhost = vhost->vhost_next;
|
2016-04-06 16:15:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|