2018-05-10 16:13:26 +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>
|
2018-05-10 16:13:26 +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:
|
2018-05-10 16:13:26 +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.
|
2018-05-10 16:13:26 +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.
|
2018-05-10 16:13:26 +08:00
|
|
|
*/
|
|
|
|
|
2019-08-15 10:49:52 +01:00
|
|
|
#include "private-lib-core.h"
|
2018-05-10 16:13:26 +08:00
|
|
|
|
|
|
|
static int
|
|
|
|
lws_get_idlest_tsi(struct lws_context *context)
|
|
|
|
{
|
2020-12-12 06:21:40 +00:00
|
|
|
unsigned int lowest = ~0u;
|
2018-05-10 16:13:26 +08:00
|
|
|
int n = 0, hit = -1;
|
|
|
|
|
|
|
|
for (; n < context->count_threads; n++) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_cx_debug(context, "%d %d\n", context->pt[n].fds_count,
|
2019-09-08 08:08:55 +01:00
|
|
|
context->fd_limit_per_thread - 1);
|
2018-05-10 16:13:26 +08:00
|
|
|
if ((unsigned int)context->pt[n].fds_count !=
|
|
|
|
context->fd_limit_per_thread - 1 &&
|
|
|
|
(unsigned int)context->pt[n].fds_count < lowest) {
|
|
|
|
lowest = context->pt[n].fds_count;
|
|
|
|
hit = n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hit;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct lws *
|
2020-12-25 05:54:19 +00:00
|
|
|
lws_create_new_server_wsi(struct lws_vhost *vhost, int fixed_tsi, const char *desc)
|
2018-05-10 16:13:26 +08:00
|
|
|
{
|
|
|
|
struct lws *new_wsi;
|
|
|
|
int n = fixed_tsi;
|
|
|
|
|
|
|
|
if (n < 0)
|
|
|
|
n = lws_get_idlest_tsi(vhost->context);
|
|
|
|
|
|
|
|
if (n < 0) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_vhost_err(vhost, "no space for new conn");
|
2018-05-10 16:13:26 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-12-24 16:06:50 +00:00
|
|
|
lws_context_lock(vhost->context, __func__);
|
2021-06-26 17:24:19 +01:00
|
|
|
new_wsi = __lws_wsi_create_with_role(vhost->context, n, NULL,
|
2021-06-28 05:05:57 +01:00
|
|
|
vhost->lc.log_cx);
|
2020-12-24 16:06:50 +00:00
|
|
|
lws_context_unlock(vhost->context);
|
2018-05-10 16:13:26 +08:00
|
|
|
if (new_wsi == NULL) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_vhost_err(vhost, "OOM");
|
2018-05-10 16:13:26 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-06-29 13:30:48 +01:00
|
|
|
lws_wsi_fault_timedclose(new_wsi);
|
|
|
|
|
2021-06-26 17:24:19 +01:00
|
|
|
__lws_lc_tag(vhost->context, &vhost->context->lcg[
|
2021-01-06 15:08:22 +00:00
|
|
|
#if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT)
|
|
|
|
strcmp(desc, "adopted") ? LWSLCG_WSI_MUX :
|
|
|
|
#endif
|
|
|
|
LWSLCG_WSI_SERVER], &new_wsi->lc, desc);
|
2020-12-25 05:54:19 +00:00
|
|
|
|
2019-04-21 19:57:19 +01:00
|
|
|
new_wsi->wsistate |= LWSIFR_SERVER;
|
2020-12-12 06:21:40 +00:00
|
|
|
new_wsi->tsi = (char)n;
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_debug(new_wsi, "joining vh %s, tsi %d",
|
|
|
|
vhost->name, new_wsi->tsi);
|
2018-05-10 16:13:26 +08:00
|
|
|
|
vhost_destroy: use vhost wsi reference counting to trigger destroy
This changes the vhost destroy flow to only hand off the listen
socket if another vhost sharing it, and mark the vhost as
being_destroyed.
Each tsi calls lws_check_deferred_free() once a second, if it sees
any vhost being_destroyed there, it closes all wsi on its tsi on
the same vhost, one time.
As the wsi on the vhost complete close (ie, after libuv async close
if on libuv event loop), they decrement a reference count for all
wsi open on the vhost. The tsi who closes the last one then
completes the destroy flow for the vhost itself... it's random
which tsi completes the vhost destroy but since there are no
wsi left on the vhost, and it holds the context lock, nothing
can conflict.
The advantage of this is that owning tsi do the close for wsi
that are bound to the vhost under destruction, at a time when
they are guaranteed to be idle for service, and they do it with
both vhost and context locks owned, so no other service thread
can conflict for stuff protected by those either.
For the situation the user code may have allocations attached to
the vhost, this adds args to lws_vhost_destroy() to allow destroying
the user allocations just before the vhost is freed.
2018-06-16 09:31:07 +08:00
|
|
|
lws_vhost_bind_wsi(vhost, new_wsi);
|
2018-05-10 16:13:26 +08:00
|
|
|
new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
|
2019-09-18 13:09:32 +01:00
|
|
|
new_wsi->retry_policy = vhost->retry_policy;
|
2018-05-10 16:13:26 +08:00
|
|
|
|
|
|
|
/* initialize the instance struct */
|
|
|
|
|
|
|
|
lwsi_set_state(new_wsi, LRS_UNCONNECTED);
|
|
|
|
new_wsi->hdr_parsing_completed = 0;
|
|
|
|
|
|
|
|
#ifdef LWS_WITH_TLS
|
|
|
|
new_wsi->tls.use_ssl = LWS_SSL_ENABLED(vhost);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* these can only be set once the protocol is known
|
|
|
|
* we set an un-established connection's protocol pointer
|
|
|
|
* to the start of the supported list, so it can look
|
|
|
|
* for matching ones during the handshake
|
|
|
|
*/
|
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
|
|
|
new_wsi->a.protocol = vhost->protocols;
|
2018-05-10 16:13:26 +08:00
|
|
|
new_wsi->user_space = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* outermost create notification for wsi
|
|
|
|
* no user_space because no protocol selection
|
|
|
|
*/
|
2018-11-23 08:47:56 +08:00
|
|
|
vhost->protocols[0].callback(new_wsi, LWS_CALLBACK_WSI_CREATE, NULL,
|
|
|
|
NULL, 0);
|
2018-05-10 16:13:26 +08:00
|
|
|
|
|
|
|
return new_wsi;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-04-04 04:06:24 +01:00
|
|
|
/* if not a socket, it's a raw, non-ssl file descriptor
|
|
|
|
* req cx lock, acq pt lock, acq vh lock
|
|
|
|
*/
|
2018-05-10 16:13:26 +08:00
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
static struct lws *
|
2021-04-04 04:06:24 +01:00
|
|
|
__lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type,
|
2019-12-08 21:26:59 +00:00
|
|
|
const char *vh_prot_name, struct lws *parent,
|
2021-03-16 13:32:05 +00:00
|
|
|
void *opaque, const char *fi_wsi_name)
|
2018-05-10 16:13:26 +08:00
|
|
|
{
|
2021-11-09 09:27:38 +00:00
|
|
|
struct lws_context *context;
|
2018-05-10 16:13:26 +08:00
|
|
|
struct lws_context_per_thread *pt;
|
2019-03-07 09:49:52 +08:00
|
|
|
struct lws *new_wsi;
|
2018-05-10 16:13:26 +08:00
|
|
|
int n;
|
|
|
|
|
2019-02-23 05:41:30 +08:00
|
|
|
/*
|
2019-03-07 09:49:52 +08:00
|
|
|
* Notice that in SMP case, the wsi may be being created on an
|
2019-02-23 05:41:30 +08:00
|
|
|
* entirely different pt / tsi for load balancing. In that case as
|
|
|
|
* we initialize it, it may become "live" concurrently unexpectedly...
|
|
|
|
*/
|
|
|
|
|
2021-11-08 10:00:17 +00:00
|
|
|
if (!vh)
|
|
|
|
return NULL;
|
|
|
|
|
2021-11-09 09:27:38 +00:00
|
|
|
context = vh->context;
|
|
|
|
|
2021-04-04 04:06:24 +01:00
|
|
|
lws_context_assert_lock_held(vh->context);
|
2020-10-01 08:39:25 +01:00
|
|
|
|
2018-05-10 16:13:26 +08:00
|
|
|
n = -1;
|
|
|
|
if (parent)
|
|
|
|
n = parent->tsi;
|
2020-12-25 05:54:19 +00:00
|
|
|
new_wsi = lws_create_new_server_wsi(vh, n, "adopted");
|
2021-04-04 04:06:24 +01:00
|
|
|
if (!new_wsi)
|
2018-05-10 16:13:26 +08:00
|
|
|
return NULL;
|
2019-09-19 06:54:53 +01:00
|
|
|
|
2021-03-16 13:32:05 +00:00
|
|
|
/* bring in specific fault injection rules early */
|
|
|
|
lws_fi_inherit_copy(&new_wsi->fic, &context->fic, "wsi", fi_wsi_name);
|
|
|
|
|
|
|
|
if (lws_fi(&new_wsi->fic, "createfail")) {
|
|
|
|
lws_fi_destroy(&new_wsi->fic);
|
2021-04-04 04:06:24 +01:00
|
|
|
|
2021-03-16 13:32:05 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
new_wsi->a.opaque_user_data = opaque;
|
2019-12-08 21:26:59 +00:00
|
|
|
|
2018-05-10 16:13:26 +08:00
|
|
|
pt = &context->pt[(int)new_wsi->tsi];
|
2020-10-01 08:39:25 +01:00
|
|
|
lws_pt_lock(pt, __func__);
|
|
|
|
|
2018-05-10 16:13:26 +08:00
|
|
|
if (parent) {
|
|
|
|
new_wsi->parent = parent;
|
|
|
|
new_wsi->sibling_list = parent->child_list;
|
|
|
|
parent->child_list = new_wsi;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vh_prot_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
|
|
|
new_wsi->a.protocol = lws_vhost_name_to_protocol(new_wsi->a.vhost,
|
2018-05-10 16:13:26 +08:00
|
|
|
vh_prot_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
|
|
|
if (!new_wsi->a.protocol) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_vhost_err(new_wsi->a.vhost, "Protocol %s not enabled",
|
|
|
|
vh_prot_name);
|
2018-05-10 16:13:26 +08:00
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
if (lws_ensure_user_space(new_wsi)) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_notice(new_wsi, "OOM");
|
2018-05-10 16:13:26 +08:00
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-20 06:53:12 +01:00
|
|
|
if (!LWS_SSL_ENABLED(new_wsi->a.vhost) ||
|
|
|
|
!(type & LWS_ADOPT_SOCKET))
|
2020-12-12 06:21:40 +00:00
|
|
|
type &= (unsigned int)~LWS_ADOPT_ALLOW_SSL;
|
2020-08-20 06:53:12 +01:00
|
|
|
|
2020-12-12 06:21:40 +00:00
|
|
|
if (lws_role_call_adoption_bind(new_wsi, (int)type, vh_prot_name)) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_err(new_wsi, "no role for desc type 0x%x", type);
|
2018-05-10 16:13:26 +08:00
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
|
2021-01-06 15:08:22 +00:00
|
|
|
#if defined(LWS_WITH_SERVER)
|
2021-06-28 11:51:44 +01:00
|
|
|
if (new_wsi->role_ops) {
|
2021-01-06 15:08:22 +00:00
|
|
|
lws_metrics_tag_wsi_add(new_wsi, "role", new_wsi->role_ops->name);
|
2021-06-28 11:51:44 +01:00
|
|
|
}
|
2021-01-06 15:08:22 +00:00
|
|
|
#endif
|
|
|
|
|
2020-10-01 08:39:25 +01:00
|
|
|
lws_pt_unlock(pt);
|
|
|
|
|
2019-09-08 08:08:55 +01:00
|
|
|
/*
|
|
|
|
* he's an allocated wsi, but he's not on any fds list or child list,
|
|
|
|
* join him to the vhost's list of these kinds of incomplete wsi until
|
|
|
|
* he gets another identity (he may do async dns now...)
|
|
|
|
*/
|
2020-08-31 08:52:54 +01:00
|
|
|
lws_vhost_lock(new_wsi->a.vhost);
|
2019-09-08 08:08:55 +01:00
|
|
|
lws_dll2_add_head(&new_wsi->vh_awaiting_socket,
|
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
|
|
|
&new_wsi->a.vhost->vh_awaiting_socket_owner);
|
2020-08-31 08:52:54 +01:00
|
|
|
lws_vhost_unlock(new_wsi->a.vhost);
|
2019-09-08 08:08:55 +01:00
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
return new_wsi;
|
|
|
|
|
|
|
|
bail:
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_notice(new_wsi, "exiting on bail");
|
2019-09-19 06:54:53 +01:00
|
|
|
if (parent)
|
|
|
|
parent->child_list = new_wsi->sibling_list;
|
|
|
|
if (new_wsi->user_space)
|
|
|
|
lws_free(new_wsi->user_space);
|
|
|
|
|
2021-03-16 13:32:05 +00:00
|
|
|
lws_fi_destroy(&new_wsi->fic);
|
|
|
|
|
2021-04-04 04:06:24 +01:00
|
|
|
lws_pt_unlock(pt);
|
|
|
|
__lws_vhost_unbind_wsi(new_wsi); /* req cx, acq vh lock */
|
2020-10-01 08:39:25 +01:00
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
lws_free(new_wsi);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-07-27 10:03:12 +01:00
|
|
|
#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_SECURE_STREAMS)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the incoming wsi is bound to a vhost that is a ss server, this creates
|
|
|
|
* an accepted ss bound to the wsi.
|
|
|
|
*
|
|
|
|
* For h1 or raw, we can do the binding here, but for muxed protocols like h2
|
|
|
|
* or mqtt we have to do it not on the nwsi but on the stream. And for h2 we
|
|
|
|
* start off bound to h1 role, since we don't know if we will upgrade to h2
|
|
|
|
* until we meet the server.
|
|
|
|
*
|
|
|
|
* 1) No tls is assumed to mean no muxed protocol so can do it at adopt.
|
|
|
|
*
|
|
|
|
* 2) After alpn if not muxed we can do it.
|
|
|
|
*
|
|
|
|
* 3) For muxed, do it at the nwsi migration and on new stream
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
lws_adopt_ss_server_accept(struct lws *new_wsi)
|
|
|
|
{
|
2020-11-10 11:27:28 +00:00
|
|
|
struct lws_context_per_thread *pt =
|
|
|
|
&new_wsi->a.context->pt[(int)new_wsi->tsi];
|
2020-07-27 10:03:12 +01:00
|
|
|
lws_ss_handle_t *h;
|
|
|
|
void *pv, **ppv;
|
|
|
|
|
|
|
|
if (!new_wsi->a.vhost->ss_handle)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
pv = (char *)&new_wsi->a.vhost->ss_handle[1];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Yes... the vhost is pointing to its secure stream representing the
|
|
|
|
* server... we want to create an accepted SS and bind it to new_wsi,
|
|
|
|
* the info/ssi from the server SS (so the SS callbacks defined there),
|
|
|
|
* the opaque_user_data of the server object and the policy of it.
|
|
|
|
*/
|
|
|
|
|
|
|
|
ppv = (void **)((char *)pv +
|
|
|
|
new_wsi->a.vhost->ss_handle->info.opaque_user_data_offset);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* indicate we are an accepted connection referencing the
|
|
|
|
* server object
|
|
|
|
*/
|
|
|
|
|
|
|
|
new_wsi->a.vhost->ss_handle->info.flags |= LWSSSINFLAGS_SERVER;
|
|
|
|
|
|
|
|
if (lws_ss_create(new_wsi->a.context, new_wsi->tsi,
|
|
|
|
&new_wsi->a.vhost->ss_handle->info,
|
|
|
|
*ppv, &h, NULL, NULL)) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_err(new_wsi, "accept ss creation failed");
|
2020-07-27 10:03:12 +01:00
|
|
|
goto fail1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We made a fresh accepted SS conn from the server pieces,
|
|
|
|
* now bind the wsi... the problem is, this is the nwsi if it's
|
|
|
|
* h2.
|
|
|
|
*/
|
|
|
|
|
|
|
|
h->wsi = new_wsi;
|
|
|
|
new_wsi->a.opaque_user_data = h;
|
|
|
|
h->info.flags |= LWSSSINFLAGS_ACCEPTED;
|
2020-11-10 11:27:28 +00:00
|
|
|
/* indicate wsi should invalidate any ss link to it on close */
|
|
|
|
new_wsi->for_ss = 1;
|
2020-07-27 10:03:12 +01:00
|
|
|
|
2021-06-28 05:05:57 +01:00
|
|
|
// lwsl_wsi_notice(new_wsi, "%s: opaq %p, role %s",
|
|
|
|
// new_wsi->a.opaque_user_data,
|
|
|
|
// new_wsi->role_ops->name);
|
2020-07-27 10:03:12 +01:00
|
|
|
|
|
|
|
h->policy = new_wsi->a.vhost->ss_handle->policy;
|
|
|
|
|
2021-02-04 09:08:17 +00:00
|
|
|
/* apply requested socket options */
|
|
|
|
if (lws_plat_set_socket_options_ip(new_wsi->desc.sockfd,
|
|
|
|
h->policy->priority,
|
|
|
|
(LCCSCF_IP_LOW_LATENCY *
|
|
|
|
!!(h->policy->flags & LWSSSPOLF_ATTR_LOW_LATENCY)) |
|
|
|
|
(LCCSCF_IP_HIGH_THROUGHPUT *
|
|
|
|
!!(h->policy->flags & LWSSSPOLF_ATTR_HIGH_THROUGHPUT)) |
|
|
|
|
(LCCSCF_IP_HIGH_RELIABILITY *
|
|
|
|
!!(h->policy->flags & LWSSSPOLF_ATTR_HIGH_RELIABILITY)) |
|
|
|
|
(LCCSCF_IP_LOW_COST *
|
|
|
|
!!(h->policy->flags & LWSSSPOLF_ATTR_LOW_COST))))
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_warn(new_wsi, "unable to set ip options");
|
2021-02-04 09:08:17 +00:00
|
|
|
|
2020-11-10 11:27:28 +00:00
|
|
|
/*
|
|
|
|
* add us to the list of clients that came in from the server
|
|
|
|
*/
|
|
|
|
|
|
|
|
lws_pt_lock(pt, __func__);
|
|
|
|
lws_dll2_add_tail(&h->cli_list, &new_wsi->a.vhost->ss_handle->src_list);
|
|
|
|
lws_pt_unlock(pt);
|
|
|
|
|
2020-07-27 10:03:12 +01:00
|
|
|
/*
|
|
|
|
* Let's give it appropriate state notifications
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (lws_ss_event_helper(h, LWSSSCS_CREATING))
|
|
|
|
goto fail;
|
|
|
|
if (lws_ss_event_helper(h, LWSSSCS_CONNECTING))
|
|
|
|
goto fail;
|
2021-01-02 10:49:43 +00:00
|
|
|
|
|
|
|
/* defer CONNECTED until we see if he is upgrading */
|
|
|
|
|
|
|
|
// if (lws_ss_event_helper(h, LWSSSCS_CONNECTED))
|
|
|
|
// goto fail;
|
2020-07-27 10:03:12 +01:00
|
|
|
|
|
|
|
// lwsl_notice("%s: accepted ss complete, pcol %s\n", __func__,
|
|
|
|
// new_wsi->a.protocol->name);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
lws_ss_destroy(&h);
|
|
|
|
fail1:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
static struct lws *
|
|
|
|
lws_adopt_descriptor_vhost2(struct lws *new_wsi, lws_adoption_type type,
|
|
|
|
lws_sock_file_fd_type fd)
|
|
|
|
{
|
|
|
|
struct lws_context_per_thread *pt =
|
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
|
|
|
&new_wsi->a.context->pt[(int)new_wsi->tsi];
|
2019-09-19 06:54:53 +01:00
|
|
|
int n;
|
|
|
|
|
|
|
|
/* enforce that every fd is nonblocking */
|
|
|
|
|
|
|
|
if (type & LWS_ADOPT_SOCKET) {
|
|
|
|
if (lws_plat_set_nonblocking(fd.sockfd)) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_err(new_wsi, "unable to set sockfd %d nonblocking",
|
|
|
|
fd.sockfd);
|
2019-09-19 06:54:53 +01:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if !defined(WIN32)
|
|
|
|
else
|
|
|
|
if (lws_plat_set_nonblocking(fd.filefd)) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_err(new_wsi, "unable to set filefd nonblocking");
|
2019-09-19 06:54:53 +01:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
new_wsi->desc = fd;
|
|
|
|
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
if (!LWS_SSL_ENABLED(new_wsi->a.vhost) ||
|
2019-09-19 06:54:53 +01:00
|
|
|
!(type & LWS_ADOPT_SOCKET))
|
2020-12-12 06:21:40 +00:00
|
|
|
type &= (unsigned int)~LWS_ADOPT_ALLOW_SSL;
|
2019-09-19 06:54:53 +01:00
|
|
|
|
2018-05-10 16:13:26 +08:00
|
|
|
/*
|
|
|
|
* A new connection was accepted. Give the user a chance to
|
|
|
|
* set properties of the newly created wsi. There's no protocol
|
|
|
|
* selected yet so we issue this to the vhosts's default protocol,
|
|
|
|
* itself by default protocols[0]
|
|
|
|
*/
|
2019-04-21 19:57:19 +01:00
|
|
|
new_wsi->wsistate |= LWSIFR_SERVER;
|
2018-05-10 16:13:26 +08:00
|
|
|
n = LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED;
|
2018-11-29 08:29:48 +08:00
|
|
|
if (new_wsi->role_ops->adoption_cb[lwsi_role_server(new_wsi)])
|
|
|
|
n = new_wsi->role_ops->adoption_cb[lwsi_role_server(new_wsi)];
|
2018-05-10 16:13:26 +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 (new_wsi->a.context->event_loop_ops->sock_accept)
|
|
|
|
if (new_wsi->a.context->event_loop_ops->sock_accept(new_wsi))
|
2018-10-13 11:59:04 +08:00
|
|
|
goto fail;
|
2018-05-10 16:13:26 +08:00
|
|
|
|
2019-02-23 05:41:30 +08:00
|
|
|
#if LWS_MAX_SMP > 1
|
|
|
|
/*
|
|
|
|
* Caution: after this point the wsi is live on its service thread
|
|
|
|
* which may be concurrent to this. We mark the wsi as still undergoing
|
|
|
|
* init in another pt so the assigned pt leaves it alone.
|
|
|
|
*/
|
|
|
|
new_wsi->undergoing_init_from_other_pt = 1;
|
|
|
|
#endif
|
|
|
|
|
2018-05-10 16:13:26 +08:00
|
|
|
if (!(type & LWS_ADOPT_ALLOW_SSL)) {
|
|
|
|
lws_pt_lock(pt, __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
|
|
|
if (__insert_wsi_socket_into_fds(new_wsi->a.context, new_wsi)) {
|
2018-05-10 16:13:26 +08:00
|
|
|
lws_pt_unlock(pt);
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_err(new_wsi, "fail inserting socket");
|
2018-05-10 16:13:26 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
lws_pt_unlock(pt);
|
2019-01-11 13:13:34 +08:00
|
|
|
}
|
2019-08-18 05:04:15 +01:00
|
|
|
#if defined(LWS_WITH_SERVER)
|
2019-01-11 13:13:34 +08:00
|
|
|
else
|
2020-04-19 08:43:01 +01:00
|
|
|
if (lws_server_socket_service_ssl(new_wsi, fd.sockfd, 0)) {
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_info(new_wsi, "fail ssl negotiation");
|
2020-10-05 06:15:10 +01:00
|
|
|
|
2018-05-10 16:13:26 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
2019-01-11 13:13:34 +08:00
|
|
|
#endif
|
2018-05-10 16:13:26 +08:00
|
|
|
|
2020-08-31 08:52:54 +01:00
|
|
|
lws_vhost_lock(new_wsi->a.vhost);
|
2019-09-08 08:08:55 +01:00
|
|
|
/* he has fds visibility now, remove from vhost orphan list */
|
|
|
|
lws_dll2_remove(&new_wsi->vh_awaiting_socket);
|
2020-08-31 08:52:54 +01:00
|
|
|
lws_vhost_unlock(new_wsi->a.vhost);
|
2019-09-08 08:08:55 +01:00
|
|
|
|
2018-05-10 16:13:26 +08:00
|
|
|
/*
|
|
|
|
* by deferring callback to this point, after insertion to fds,
|
|
|
|
* lws_callback_on_writable() can work from the callback
|
|
|
|
*/
|
2020-12-12 06:21:40 +00:00
|
|
|
if ((new_wsi->a.protocol->callback)(new_wsi, (enum lws_callback_reasons)n, new_wsi->user_space,
|
2018-11-23 08:47:56 +08:00
|
|
|
NULL, 0))
|
2018-05-10 16:13:26 +08:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
/* role may need to do something after all adoption completed */
|
|
|
|
|
2020-12-12 06:21:40 +00:00
|
|
|
lws_role_call_adoption_bind(new_wsi, (int)type | _LWS_ADOPT_FINISH,
|
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
|
|
|
new_wsi->a.protocol->name);
|
2018-05-10 16:13:26 +08:00
|
|
|
|
2020-07-27 10:03:12 +01:00
|
|
|
#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_SECURE_STREAMS)
|
|
|
|
/*
|
|
|
|
* Did we come from an accepted client connection to a ss server?
|
|
|
|
*
|
|
|
|
* !!! For mux protocols, this will cause an additional inactive ss
|
|
|
|
* representing the nwsi. Doing that allows us to support both h1
|
2021-04-04 04:06:24 +01:00
|
|
|
* (here) and h2 (at __lws_wsi_server_new())
|
2020-07-27 10:03:12 +01:00
|
|
|
*/
|
|
|
|
|
2021-06-28 05:05:57 +01:00
|
|
|
lwsl_wsi_info(new_wsi, "vhost %s", new_wsi->a.vhost->lc.gutag);
|
2020-07-27 10:03:12 +01:00
|
|
|
|
|
|
|
if (lws_adopt_ss_server_accept(new_wsi))
|
|
|
|
goto fail;
|
|
|
|
#endif
|
|
|
|
|
2019-02-23 05:41:30 +08:00
|
|
|
#if LWS_MAX_SMP > 1
|
|
|
|
/* its actual pt can service it now */
|
|
|
|
|
|
|
|
new_wsi->undergoing_init_from_other_pt = 0;
|
|
|
|
#endif
|
|
|
|
|
2018-05-10 16:13:26 +08:00
|
|
|
lws_cancel_service_pt(new_wsi);
|
|
|
|
|
|
|
|
return new_wsi;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
if (type & LWS_ADOPT_SOCKET)
|
|
|
|
lws_close_free_wsi(new_wsi, LWS_CLOSE_STATUS_NOSTATUS,
|
|
|
|
"adopt skt fail");
|
|
|
|
|
|
|
|
return NULL;
|
2019-09-19 06:54:53 +01:00
|
|
|
}
|
2018-05-10 16:13:26 +08:00
|
|
|
|
2018-09-04 08:06:46 +08:00
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
/* if not a socket, it's a raw, non-ssl file descriptor */
|
2018-09-04 08:06:46 +08:00
|
|
|
|
2019-12-08 21:26:59 +00:00
|
|
|
struct lws *
|
2019-09-19 06:54:53 +01:00
|
|
|
lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
|
|
|
|
lws_sock_file_fd_type fd, const char *vh_prot_name,
|
|
|
|
struct lws *parent)
|
2019-12-08 21:26:59 +00:00
|
|
|
{
|
|
|
|
lws_adopt_desc_t info;
|
|
|
|
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
|
|
|
|
info.vh = vh;
|
|
|
|
info.type = type;
|
|
|
|
info.fd = fd;
|
|
|
|
info.vh_prot_name = vh_prot_name;
|
|
|
|
info.parent = parent;
|
|
|
|
|
|
|
|
return lws_adopt_descriptor_vhost_via_info(&info);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct lws *
|
|
|
|
lws_adopt_descriptor_vhost_via_info(const lws_adopt_desc_t *info)
|
2019-09-19 06:54:53 +01:00
|
|
|
{
|
2020-10-05 08:21:28 +01:00
|
|
|
socklen_t slen = sizeof(lws_sockaddr46);
|
2019-09-19 06:54:53 +01:00
|
|
|
struct lws *new_wsi;
|
2020-10-05 06:15:10 +01:00
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
#if defined(LWS_WITH_PEER_LIMITS)
|
|
|
|
struct lws_peer *peer = NULL;
|
vhost_destroy: use vhost wsi reference counting to trigger destroy
This changes the vhost destroy flow to only hand off the listen
socket if another vhost sharing it, and mark the vhost as
being_destroyed.
Each tsi calls lws_check_deferred_free() once a second, if it sees
any vhost being_destroyed there, it closes all wsi on its tsi on
the same vhost, one time.
As the wsi on the vhost complete close (ie, after libuv async close
if on libuv event loop), they decrement a reference count for all
wsi open on the vhost. The tsi who closes the last one then
completes the destroy flow for the vhost itself... it's random
which tsi completes the vhost destroy but since there are no
wsi left on the vhost, and it holds the context lock, nothing
can conflict.
The advantage of this is that owning tsi do the close for wsi
that are bound to the vhost under destruction, at a time when
they are guaranteed to be idle for service, and they do it with
both vhost and context locks owned, so no other service thread
can conflict for stuff protected by those either.
For the situation the user code may have allocations attached to
the vhost, this adds args to lws_vhost_destroy() to allow destroying
the user allocations just before the vhost is freed.
2018-06-16 09:31:07 +08:00
|
|
|
|
2019-12-08 21:26:59 +00:00
|
|
|
if (info->type & LWS_ADOPT_SOCKET) {
|
|
|
|
peer = lws_get_or_create_peer(info->vh, info->fd.sockfd);
|
2018-05-10 16:13:26 +08:00
|
|
|
|
2019-12-08 21:26:59 +00:00
|
|
|
if (peer && info->vh->context->ip_limit_wsi &&
|
|
|
|
peer->count_wsi >= info->vh->context->ip_limit_wsi) {
|
2020-05-24 19:44:46 +01:00
|
|
|
lwsl_info("Peer reached wsi limit %d\n",
|
2019-12-08 21:26:59 +00:00
|
|
|
info->vh->context->ip_limit_wsi);
|
2020-05-24 19:44:46 +01:00
|
|
|
if (info->vh->context->pl_notify_cb)
|
|
|
|
info->vh->context->pl_notify_cb(
|
|
|
|
info->vh->context,
|
|
|
|
info->fd.sockfd,
|
|
|
|
&peer->sa46);
|
2020-05-24 17:14:51 +01:00
|
|
|
compatible_close(info->fd.sockfd);
|
2019-09-19 06:54:53 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-04-04 04:06:24 +01:00
|
|
|
lws_context_lock(info->vh->context, __func__);
|
|
|
|
|
|
|
|
new_wsi = __lws_adopt_descriptor_vhost1(info->vh, info->type,
|
2019-12-08 21:26:59 +00:00
|
|
|
info->vh_prot_name, info->parent,
|
2021-03-16 13:32:05 +00:00
|
|
|
info->opaque, info->fi_wsi_name);
|
2019-09-19 06:54:53 +01:00
|
|
|
if (!new_wsi) {
|
2019-12-08 21:26:59 +00:00
|
|
|
if (info->type & LWS_ADOPT_SOCKET)
|
|
|
|
compatible_close(info->fd.sockfd);
|
2021-04-04 04:06:24 +01:00
|
|
|
goto bail;
|
2019-09-19 06:54:53 +01:00
|
|
|
}
|
|
|
|
|
2020-10-05 08:21:28 +01:00
|
|
|
if (info->type & LWS_ADOPT_SOCKET &&
|
|
|
|
getpeername(info->fd.sockfd, (struct sockaddr *)&new_wsi->sa46_peer,
|
|
|
|
&slen) < 0)
|
|
|
|
lwsl_info("%s: getpeername failed\n", __func__);
|
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
#if defined(LWS_WITH_PEER_LIMITS)
|
|
|
|
if (peer)
|
2019-12-08 21:26:59 +00:00
|
|
|
lws_peer_add_wsi(info->vh->context, peer, new_wsi);
|
2019-09-19 06:54:53 +01:00
|
|
|
#endif
|
|
|
|
|
2021-04-04 04:06:24 +01:00
|
|
|
new_wsi = lws_adopt_descriptor_vhost2(new_wsi, info->type, info->fd);
|
|
|
|
|
|
|
|
bail:
|
|
|
|
lws_context_unlock(info->vh->context);
|
|
|
|
|
|
|
|
return new_wsi;
|
2018-05-10 16:13:26 +08:00
|
|
|
}
|
|
|
|
|
2019-12-08 21:26:59 +00:00
|
|
|
struct lws *
|
2018-05-10 16:13:26 +08:00
|
|
|
lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd)
|
|
|
|
{
|
|
|
|
lws_sock_file_fd_type fd;
|
|
|
|
|
|
|
|
fd.sockfd = accept_fd;
|
|
|
|
return lws_adopt_descriptor_vhost(vh, LWS_ADOPT_SOCKET |
|
|
|
|
LWS_ADOPT_HTTP | LWS_ADOPT_ALLOW_SSL, fd, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
struct lws *
|
2018-05-10 16:13:26 +08:00
|
|
|
lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd)
|
|
|
|
{
|
|
|
|
return lws_adopt_socket_vhost(context->vhost_list, accept_fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Common read-buffer adoption for lws_adopt_*_readbuf */
|
|
|
|
static struct lws*
|
|
|
|
adopt_socket_readbuf(struct lws *wsi, const char *readbuf, size_t len)
|
|
|
|
{
|
|
|
|
struct lws_context_per_thread *pt;
|
|
|
|
struct lws_pollfd *pfd;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
if (!wsi)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!readbuf || len == 0)
|
|
|
|
return wsi;
|
|
|
|
|
|
|
|
if (wsi->position_in_fds_table == LWS_NO_FDS_POS)
|
|
|
|
return 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
|
|
|
pt = &wsi->a.context->pt[(int)wsi->tsi];
|
2018-05-10 16:13:26 +08:00
|
|
|
|
|
|
|
n = lws_buflist_append_segment(&wsi->buflist, (const uint8_t *)readbuf,
|
|
|
|
len);
|
|
|
|
if (n < 0)
|
|
|
|
goto bail;
|
|
|
|
if (n)
|
2019-04-21 06:24:05 +01:00
|
|
|
lws_dll2_add_head(&wsi->dll_buflist, &pt->dll_buflist_owner);
|
2018-05-10 16:13:26 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* we can't process the initial read data until we can attach an ah.
|
|
|
|
*
|
|
|
|
* if one is available, get it and place the data in his ah rxbuf...
|
|
|
|
* wsi with ah that have pending rxbuf get auto-POLLIN service.
|
|
|
|
*
|
|
|
|
* no autoservice because we didn't get a chance to attach the
|
|
|
|
* readbuf data to wsi or ah yet, and we will do it next if we get
|
|
|
|
* the ah.
|
|
|
|
*/
|
|
|
|
if (wsi->http.ah || !lws_header_table_attach(wsi, 0)) {
|
|
|
|
|
|
|
|
lwsl_notice("%s: calling service on readbuf ah\n", __func__);
|
|
|
|
|
2018-11-23 08:47:56 +08:00
|
|
|
/*
|
|
|
|
* unlike a normal connect, we have the headers already
|
2018-05-10 16:13:26 +08:00
|
|
|
* (or the first part of them anyway).
|
|
|
|
* libuv won't come back and service us without a network
|
|
|
|
* event, so we need to do the header service right here.
|
|
|
|
*/
|
|
|
|
pfd = &pt->fds[wsi->position_in_fds_table];
|
|
|
|
pfd->revents |= LWS_POLLIN;
|
|
|
|
lwsl_err("%s: calling service\n", __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
|
|
|
if (lws_service_fd_tsi(wsi->a.context, pfd, wsi->tsi))
|
2018-05-10 16:13:26 +08:00
|
|
|
/* service closed us */
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return wsi;
|
|
|
|
}
|
|
|
|
lwsl_err("%s: deferring handling ah\n", __func__);
|
|
|
|
|
|
|
|
return wsi;
|
|
|
|
|
|
|
|
bail:
|
|
|
|
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
|
|
|
|
"adopt skt readbuf fail");
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-09-30 09:42:38 -07:00
|
|
|
#if defined(LWS_WITH_UDP)
|
2019-09-19 06:54:53 +01:00
|
|
|
#if defined(LWS_WITH_CLIENT)
|
2020-09-20 09:14:46 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This is the ASYNC_DNS callback target for udp client, it's analogous to
|
|
|
|
* connect3()
|
|
|
|
*/
|
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
static struct lws *
|
|
|
|
lws_create_adopt_udp2(struct lws *wsi, const char *ads,
|
|
|
|
const struct addrinfo *r, int n, void *opaque)
|
2018-05-10 16:13:26 +08:00
|
|
|
{
|
|
|
|
lws_sock_file_fd_type sock;
|
2020-09-20 09:14:46 +01:00
|
|
|
int bc = 1, m;
|
2018-05-10 16:13:26 +08:00
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
assert(wsi);
|
2018-05-10 16:13:26 +08:00
|
|
|
|
2019-10-05 12:47:42 +01:00
|
|
|
if (ads && (n < 0 || !r)) {
|
2019-09-08 08:08:55 +01:00
|
|
|
/*
|
|
|
|
* DNS lookup failed: there are no usable results. Fail the
|
|
|
|
* overall connection request.
|
|
|
|
*/
|
2019-10-05 12:47:42 +01:00
|
|
|
lwsl_notice("%s: bad: n %d, r %p\n", __func__, n, r);
|
2019-09-08 08:08:55 +01:00
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
goto bail;
|
2019-09-08 08:08:55 +01:00
|
|
|
}
|
2019-09-19 06:54:53 +01:00
|
|
|
|
2020-09-20 09:14:46 +01:00
|
|
|
m = lws_sort_dns(wsi, r);
|
|
|
|
#if defined(LWS_WITH_SYS_ASYNC_DNS)
|
|
|
|
lws_async_dns_freeaddrinfo(&r);
|
|
|
|
#else
|
|
|
|
freeaddrinfo((struct addrinfo *)r);
|
|
|
|
#endif
|
|
|
|
if (m)
|
|
|
|
goto bail;
|
|
|
|
|
|
|
|
while (lws_dll2_get_head(&wsi->dns_sorted_list)) {
|
|
|
|
lws_dns_sort_t *s = lws_container_of(
|
|
|
|
lws_dll2_get_head(&wsi->dns_sorted_list),
|
|
|
|
lws_dns_sort_t, list);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove it from the head, but don't free it yet... we are
|
|
|
|
* taking responsibility to free it
|
|
|
|
*/
|
|
|
|
lws_dll2_remove(&s->list);
|
2019-09-19 06:54:53 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We have done the dns lookup, identify the result we want
|
|
|
|
* if any, and then complete the adoption by binding wsi to
|
|
|
|
* socket opened on it.
|
|
|
|
*
|
|
|
|
* Ignore the weak assumptions about protocol driven by port
|
|
|
|
* number and force to DGRAM / UDP since that's what this
|
|
|
|
* function is for.
|
|
|
|
*/
|
|
|
|
|
2019-10-05 12:47:42 +01:00
|
|
|
#if !defined(__linux__)
|
2020-09-20 09:14:46 +01:00
|
|
|
sock.sockfd = socket(s->dest.sa4.sin_family,
|
2019-09-19 06:54:53 +01:00
|
|
|
SOCK_DGRAM, IPPROTO_UDP);
|
2019-10-05 12:47:42 +01:00
|
|
|
#else
|
2020-09-20 09:14:46 +01:00
|
|
|
/* PF_PACKET is linux-only */
|
2019-10-05 12:47:42 +01:00
|
|
|
sock.sockfd = socket(wsi->pf_packet ? PF_PACKET :
|
2020-09-20 09:14:46 +01:00
|
|
|
s->dest.sa4.sin_family,
|
2019-10-05 12:47:42 +01:00
|
|
|
SOCK_DGRAM, wsi->pf_packet ?
|
|
|
|
htons(0x800) : IPPROTO_UDP);
|
|
|
|
#endif
|
2019-09-19 06:54:53 +01:00
|
|
|
if (sock.sockfd == LWS_SOCK_INVALID)
|
|
|
|
goto resume;
|
|
|
|
|
2020-09-20 09:14:46 +01:00
|
|
|
/* ipv6 udp!!! */
|
|
|
|
|
|
|
|
if (s->af == AF_INET)
|
|
|
|
s->dest.sa4.sin_port = htons(wsi->c_port);
|
|
|
|
#if defined(LWS_WITH_IPV6)
|
|
|
|
else
|
|
|
|
s->dest.sa6.sin6_port = htons(wsi->c_port);
|
|
|
|
#endif
|
2019-10-05 12:47:42 +01:00
|
|
|
|
2020-09-20 09:14:46 +01:00
|
|
|
if (setsockopt(sock.sockfd, SOL_SOCKET, SO_REUSEADDR,
|
|
|
|
(const char *)&bc, sizeof(bc)) < 0)
|
2019-10-05 12:47:42 +01:00
|
|
|
lwsl_err("%s: failed to set reuse\n", __func__);
|
|
|
|
|
|
|
|
if (wsi->do_broadcast &&
|
2020-09-20 09:14:46 +01:00
|
|
|
setsockopt(sock.sockfd, SOL_SOCKET, SO_BROADCAST,
|
|
|
|
(const char *)&bc, sizeof(bc)) < 0)
|
|
|
|
lwsl_err("%s: failed to set broadcast\n", __func__);
|
2019-10-05 12:47:42 +01:00
|
|
|
|
|
|
|
/* Bind the udp socket to a particular network interface */
|
|
|
|
|
|
|
|
if (opaque &&
|
|
|
|
lws_plat_BINDTODEVICE(sock.sockfd, (const char *)opaque))
|
|
|
|
goto resume;
|
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
if (wsi->do_bind &&
|
2020-09-20 09:14:46 +01:00
|
|
|
bind(sock.sockfd, sa46_sockaddr(&s->dest),
|
2019-09-19 06:54:53 +01:00
|
|
|
#if defined(_WIN32)
|
2020-09-20 09:14:46 +01:00
|
|
|
(int)sa46_socklen(&s->dest)
|
2019-07-01 14:53:54 +01:00
|
|
|
#else
|
2020-09-20 09:14:46 +01:00
|
|
|
sizeof(struct sockaddr)
|
2019-07-01 14:53:54 +01:00
|
|
|
#endif
|
2020-09-20 09:14:46 +01:00
|
|
|
) == -1) {
|
2019-10-05 12:47:42 +01:00
|
|
|
lwsl_err("%s: bind failed\n", __func__);
|
2019-09-19 06:54:53 +01:00
|
|
|
goto resume;
|
|
|
|
}
|
|
|
|
|
2019-10-05 12:47:42 +01:00
|
|
|
if (!wsi->do_bind && !wsi->pf_packet) {
|
2020-04-17 07:05:13 +01:00
|
|
|
#if !defined(__APPLE__)
|
2020-09-20 09:14:46 +01:00
|
|
|
if (connect(sock.sockfd, sa46_sockaddr(&s->dest),
|
2021-02-23 09:15:05 +00:00
|
|
|
sa46_socklen(&s->dest)) == -1 &&
|
|
|
|
errno != EADDRNOTAVAIL /* openbsd */ ) {
|
2019-09-19 06:54:53 +01:00
|
|
|
lwsl_err("%s: conn fd %d fam %d %s:%u failed "
|
2020-09-20 09:14:46 +01:00
|
|
|
"errno %d\n", __func__, sock.sockfd,
|
|
|
|
s->dest.sa4.sin_family,
|
2019-09-19 06:54:53 +01:00
|
|
|
ads ? ads : "null", wsi->c_port,
|
|
|
|
LWS_ERRNO);
|
|
|
|
compatible_close(sock.sockfd);
|
|
|
|
goto resume;
|
|
|
|
}
|
2020-04-17 07:05:13 +01:00
|
|
|
#endif
|
2019-09-19 06:54:53 +01:00
|
|
|
}
|
|
|
|
|
2020-09-20 09:14:46 +01:00
|
|
|
if (wsi->udp)
|
|
|
|
wsi->udp->sa46 = s->dest;
|
|
|
|
wsi->sa46_peer = s->dest;
|
|
|
|
|
2019-09-08 08:08:55 +01:00
|
|
|
/* we connected: complete the udp socket adoption flow */
|
2018-05-10 16:13:26 +08:00
|
|
|
|
2021-02-05 13:08:41 +00:00
|
|
|
#if defined(LWS_WITH_SYS_ASYNC_DNS)
|
|
|
|
if (wsi->a.context->async_dns.wsi == wsi)
|
|
|
|
wsi->a.context->async_dns.dns_server_connected = 1;
|
|
|
|
#endif
|
|
|
|
|
2020-09-20 09:14:46 +01:00
|
|
|
lws_free(s);
|
2019-09-19 06:54:53 +01:00
|
|
|
lws_addrinfo_clean(wsi);
|
|
|
|
return lws_adopt_descriptor_vhost2(wsi,
|
|
|
|
LWS_ADOPT_RAW_SOCKET_UDP, sock);
|
|
|
|
|
|
|
|
resume:
|
2020-09-20 09:14:46 +01:00
|
|
|
lws_free(s);
|
2018-05-10 16:13:26 +08:00
|
|
|
}
|
2019-09-19 06:54:53 +01:00
|
|
|
|
2019-10-05 12:47:42 +01:00
|
|
|
lwsl_err("%s: unable to create INET socket %d\n", __func__, LWS_ERRNO);
|
2019-09-19 06:54:53 +01:00
|
|
|
lws_addrinfo_clean(wsi);
|
|
|
|
|
2021-02-05 13:08:41 +00:00
|
|
|
#if defined(LWS_WITH_SYS_ASYNC_DNS)
|
|
|
|
if (wsi->a.context->async_dns.wsi == wsi)
|
|
|
|
lws_async_dns_drop_server(wsi->a.context);
|
|
|
|
#endif
|
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
bail:
|
2020-09-20 09:14:46 +01:00
|
|
|
|
|
|
|
/* caller must close */
|
2019-09-19 06:54:53 +01:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct lws *
|
|
|
|
lws_create_adopt_udp(struct lws_vhost *vhost, const char *ads, int port,
|
2019-10-05 12:47:42 +01:00
|
|
|
int flags, const char *protocol_name, const char *ifname,
|
2019-12-08 21:26:59 +00:00
|
|
|
struct lws *parent_wsi, void *opaque,
|
2021-03-16 13:32:05 +00:00
|
|
|
const lws_retry_bo_t *retry_policy, const char *fi_wsi_name)
|
2019-09-19 06:54:53 +01:00
|
|
|
{
|
|
|
|
#if !defined(LWS_PLAT_OPTEE)
|
|
|
|
struct lws *wsi;
|
2019-09-08 08:08:55 +01:00
|
|
|
int n;
|
2019-09-19 06:54:53 +01:00
|
|
|
|
|
|
|
lwsl_info("%s: %s:%u\n", __func__, ads ? ads : "null", port);
|
|
|
|
|
|
|
|
/* create the logical wsi without any valid fd */
|
|
|
|
|
2021-04-04 04:06:24 +01:00
|
|
|
lws_context_lock(vhost->context, __func__);
|
|
|
|
|
|
|
|
wsi = __lws_adopt_descriptor_vhost1(vhost, LWS_ADOPT_SOCKET |
|
2021-03-16 13:32:05 +00:00
|
|
|
LWS_ADOPT_RAW_SOCKET_UDP,
|
|
|
|
protocol_name, parent_wsi, opaque,
|
|
|
|
fi_wsi_name);
|
2021-04-04 04:06:24 +01:00
|
|
|
|
|
|
|
lws_context_unlock(vhost->context);
|
2019-09-19 06:54:53 +01:00
|
|
|
if (!wsi) {
|
|
|
|
lwsl_err("%s: udp wsi creation failed\n", __func__);
|
|
|
|
goto bail;
|
2018-05-10 16:13:26 +08:00
|
|
|
}
|
2020-09-20 09:14:46 +01:00
|
|
|
|
|
|
|
// lwsl_notice("%s: role %s\n", __func__, wsi->role_ops->name);
|
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
wsi->do_bind = !!(flags & LWS_CAUDP_BIND);
|
2019-10-05 12:47:42 +01:00
|
|
|
wsi->do_broadcast = !!(flags & LWS_CAUDP_BROADCAST);
|
|
|
|
wsi->pf_packet = !!(flags & LWS_CAUDP_PF_PACKET);
|
2020-12-12 06:21:40 +00:00
|
|
|
wsi->c_port = (uint16_t)(unsigned int)port;
|
2019-09-08 08:08:55 +01:00
|
|
|
if (retry_policy)
|
|
|
|
wsi->retry_policy = retry_policy;
|
|
|
|
else
|
|
|
|
wsi->retry_policy = vhost->retry_policy;
|
2019-09-19 06:54:53 +01:00
|
|
|
|
|
|
|
#if !defined(LWS_WITH_SYS_ASYNC_DNS)
|
|
|
|
{
|
|
|
|
struct addrinfo *r, h;
|
|
|
|
char buf[16];
|
|
|
|
|
|
|
|
memset(&h, 0, sizeof(h));
|
|
|
|
h.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
|
|
|
|
h.ai_socktype = SOCK_DGRAM;
|
|
|
|
h.ai_protocol = IPPROTO_UDP;
|
2020-09-03 12:49:54 +01:00
|
|
|
#if defined(AI_PASSIVE)
|
2019-09-19 06:54:53 +01:00
|
|
|
h.ai_flags = AI_PASSIVE;
|
2020-09-03 12:49:54 +01:00
|
|
|
#endif
|
2019-09-19 06:54:53 +01:00
|
|
|
#ifdef AI_ADDRCONFIG
|
|
|
|
h.ai_flags |= AI_ADDRCONFIG;
|
|
|
|
#endif
|
2018-05-10 16:13:26 +08:00
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
/* if the dns lookup is synchronous, do the whole thing now */
|
|
|
|
lws_snprintf(buf, sizeof(buf), "%u", port);
|
|
|
|
n = getaddrinfo(ads, buf, &h, &r);
|
|
|
|
if (n) {
|
2022-02-01 07:59:41 +00:00
|
|
|
|
|
|
|
#if (_LWS_ENABLED_LOGS & LLL_INFO)
|
2019-09-19 06:54:53 +01:00
|
|
|
#if !defined(LWS_PLAT_FREERTOS)
|
|
|
|
lwsl_info("%s: getaddrinfo error: %s\n", __func__,
|
|
|
|
gai_strerror(n));
|
2018-05-10 16:13:26 +08:00
|
|
|
#else
|
2022-02-01 07:59:41 +00:00
|
|
|
|
2019-09-19 09:48:17 +01:00
|
|
|
lwsl_info("%s: getaddrinfo error: %s\n", __func__,
|
|
|
|
strerror(n));
|
2022-02-01 07:59:41 +00:00
|
|
|
#endif
|
2018-05-10 16:13:26 +08:00
|
|
|
#endif
|
2019-12-06 17:14:28 +00:00
|
|
|
//freeaddrinfo(r);
|
2019-09-19 06:54:53 +01:00
|
|
|
goto bail1;
|
|
|
|
}
|
2021-02-05 13:08:41 +00:00
|
|
|
/*
|
|
|
|
* With synchronous dns, complete it immediately after the
|
|
|
|
* blocking dns lookup finished... free r when connect either
|
|
|
|
* completed or failed
|
|
|
|
*/
|
2019-09-19 06:54:53 +01:00
|
|
|
wsi = lws_create_adopt_udp2(wsi, ads, r, 0, NULL);
|
|
|
|
|
|
|
|
return wsi;
|
2018-05-10 16:13:26 +08:00
|
|
|
}
|
2019-09-19 06:54:53 +01:00
|
|
|
#else
|
|
|
|
if (ads) {
|
|
|
|
/*
|
|
|
|
* with async dns, use the wsi as the point about which to do
|
|
|
|
* the dns lookup and have it call the second part when it's
|
|
|
|
* done.
|
|
|
|
*
|
|
|
|
* Keep a refcount on the results and free it when we connected
|
|
|
|
* or definitively failed.
|
2019-09-08 08:08:55 +01:00
|
|
|
*
|
|
|
|
* Notice wsi has no socket at this point (we don't know what
|
|
|
|
* kind to ask for until we get the dns back). But it is bound
|
|
|
|
* to a vhost and can be cleaned up from that at vhost destroy.
|
2019-09-19 06:54:53 +01:00
|
|
|
*/
|
2019-09-08 08:08:55 +01:00
|
|
|
n = lws_async_dns_query(vhost->context, 0, ads,
|
2019-09-19 06:54:53 +01:00
|
|
|
LWS_ADNS_RECORD_A,
|
2020-09-20 09:14:46 +01:00
|
|
|
lws_create_adopt_udp2, wsi,
|
|
|
|
(void *)ifname);
|
|
|
|
// lwsl_notice("%s: dns query returned %d\n", __func__, n);
|
2019-09-08 08:08:55 +01:00
|
|
|
if (n == LADNS_RET_FAILED) {
|
2019-09-19 06:54:53 +01:00
|
|
|
lwsl_err("%s: async dns failed\n", __func__);
|
2019-09-19 09:48:17 +01:00
|
|
|
wsi = NULL;
|
|
|
|
/*
|
|
|
|
* It was already closed by calling callback with error
|
|
|
|
* from lws_async_dns_query()
|
|
|
|
*/
|
|
|
|
goto bail;
|
2019-09-19 06:54:53 +01:00
|
|
|
}
|
2019-09-08 08:08:55 +01:00
|
|
|
} else {
|
2019-10-05 12:47:42 +01:00
|
|
|
lwsl_debug("%s: udp adopt has no ads\n", __func__);
|
|
|
|
wsi = lws_create_adopt_udp2(wsi, ads, NULL, 0, (void *)ifname);
|
2019-09-08 08:08:55 +01:00
|
|
|
}
|
2018-05-10 16:13:26 +08:00
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
/* dns lookup is happening asynchronously */
|
2018-05-10 16:13:26 +08:00
|
|
|
|
2020-09-20 09:14:46 +01:00
|
|
|
// lwsl_notice("%s: returning wsi %p\n", __func__, wsi);
|
2021-04-04 04:06:24 +01:00
|
|
|
|
2019-09-19 06:54:53 +01:00
|
|
|
return wsi;
|
|
|
|
#endif
|
2019-09-19 09:48:17 +01:00
|
|
|
#if !defined(LWS_WITH_SYS_ASYNC_DNS)
|
2019-09-19 06:54:53 +01:00
|
|
|
bail1:
|
2019-09-19 09:48:17 +01:00
|
|
|
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "adopt udp2 fail");
|
2019-12-06 17:14:28 +00:00
|
|
|
wsi = NULL;
|
2019-09-19 09:48:17 +01:00
|
|
|
#endif
|
2018-05-10 16:13:26 +08:00
|
|
|
bail:
|
|
|
|
return wsi;
|
2019-02-05 21:13:09 +08:00
|
|
|
#else
|
|
|
|
return NULL;
|
|
|
|
#endif
|
2018-05-10 16:13:26 +08:00
|
|
|
}
|
2019-09-19 06:54:53 +01:00
|
|
|
#endif
|
2019-09-30 09:42:38 -07:00
|
|
|
#endif
|
2018-05-10 16:13:26 +08:00
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
struct lws *
|
2018-05-10 16:13:26 +08:00
|
|
|
lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd,
|
|
|
|
const char *readbuf, size_t len)
|
|
|
|
{
|
|
|
|
return adopt_socket_readbuf(lws_adopt_socket(context, accept_fd),
|
2018-11-23 08:47:56 +08:00
|
|
|
readbuf, len);
|
2018-05-10 16:13:26 +08:00
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
struct lws *
|
2018-05-10 16:13:26 +08:00
|
|
|
lws_adopt_socket_vhost_readbuf(struct lws_vhost *vhost,
|
|
|
|
lws_sockfd_type accept_fd,
|
|
|
|
const char *readbuf, size_t len)
|
|
|
|
{
|
|
|
|
return adopt_socket_readbuf(lws_adopt_socket_vhost(vhost, accept_fd),
|
2018-11-23 08:47:56 +08:00
|
|
|
readbuf, len);
|
2018-05-10 16:13:26 +08:00
|
|
|
}
|