1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

vhost: allow multiple listen sockets

Some platforms need two sockets with AF_INET and AF_INET6 to listen to both
protocols.

This patch changes the single listen socket each vhost could previously
handle to become an lws_dll2 and adapts the related code to handle them as
a linked-list rather than as a singleton.

The next patch adapts the listen / server code to create multiple listen
wsi for vhosts listening on multiple ip protocols.
This commit is contained in:
Andy Green 2021-06-21 08:50:13 +01:00
parent 8c122cd8bd
commit 6163c96727
14 changed files with 295 additions and 214 deletions

View file

@ -228,9 +228,11 @@ lws_dll2_add_tail(struct lws_dll2 *d, struct lws_dll2_owner *owner);
LWS_VISIBLE LWS_EXTERN void
lws_dll2_remove(struct lws_dll2 *d);
typedef int (*lws_dll2_foreach_cb_t)(struct lws_dll2 *d, void *user);
LWS_VISIBLE LWS_EXTERN int
lws_dll2_foreach_safe(struct lws_dll2_owner *owner, void *user,
int (*cb)(struct lws_dll2 *d, void *user));
lws_dll2_foreach_cb_t cb);
LWS_VISIBLE LWS_EXTERN void
lws_dll2_clear(struct lws_dll2 *d);

View file

@ -96,6 +96,10 @@ LWS_VISIBLE LWS_EXTERN void
lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason,
const char *caller);
LWS_VISIBLE LWS_EXTERN int
lws_vhost_foreach_listen_wsi(struct lws_context *cx, void *arg,
lws_dll2_foreach_cb_t cb);
struct lws_context_per_thread;
LWS_VISIBLE LWS_EXTERN void
lws_service_do_ripe_rxflow(struct lws_context_per_thread *pt);

View file

@ -136,8 +136,10 @@ __lws_reset_wsi(struct lws *wsi)
lws_buflist_destroy_all_segments(&wsi->http.buflist_post_body);
#endif
if (wsi->a.vhost && wsi->a.vhost->lserv_wsi == wsi)
wsi->a.vhost->lserv_wsi = NULL;
#if defined(LWS_WITH_SERVER)
lws_dll2_remove(&wsi->listen_list);
#endif
#if defined(LWS_WITH_CLIENT)
if (wsi->a.vhost)
lws_dll2_remove(&wsi->dll_cli_active_conns);

View file

@ -230,14 +230,15 @@ lws_accept_modulation(struct lws_context *context,
struct lws_pollargs pa1;
while (vh) {
if (vh->lserv_wsi) {
if (allow)
_lws_change_pollfd(vh->lserv_wsi,
0, LWS_POLLIN, &pa1);
else
_lws_change_pollfd(vh->lserv_wsi,
LWS_POLLIN, 0, &pa1);
}
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);
vh = vh->vhost_next;
}
}

View file

@ -480,7 +480,8 @@ struct lws_vhost {
lws_ss_handle_t *ss_handle; /* ss handle for the server obj */
#endif
struct lws *lserv_wsi;
lws_dll2_owner_t listen_wsi;
const char *name;
const char *iface;
const char *listen_accept_role;
@ -682,6 +683,9 @@ struct lws {
struct lws_dll2 dll_cli_active_conns;
struct lws_dll2 dll2_cli_txn_queue;
struct lws_dll2_owner dll2_cli_txn_queue_owner;
#if defined(LWS_WITH_SERVER)
struct lws_dll2 listen_list;
#endif
/**< caliper is reused for tcp, tls and txn conn phases */
@ -1532,6 +1536,9 @@ lws_sul_nonmonotonic_adjust(struct lws_context *ctx, int64_t step_us);
void
__lws_vhost_destroy_pt_wsi_dieback_start(struct lws_vhost *vh);
int
lws_vhost_compare_listen(struct lws_vhost *v1, struct lws_vhost *v2);
void
lws_netdev_instance_remove_destroy(struct lws_netdev_instance *ni);

View file

@ -1211,6 +1211,35 @@ __lws_vhost_destroy_pt_wsi_dieback_start(struct lws_vhost *vh)
#endif
}
#if defined(LWS_WITH_NETWORK)
int
lws_vhost_compare_listen(struct lws_vhost *v1, struct lws_vhost *v2)
{
return ((!v1->iface && !v2->iface) ||
(v1->iface && v2->iface && !strcmp(v1->iface, v2->iface))) &&
v1->listen_port == v2->listen_port;
}
int
lws_vhost_foreach_listen_wsi(struct lws_context *cx, void *arg,
lws_dll2_foreach_cb_t cb)
{
struct lws_vhost *v = cx->vhost_list;
int n;
while (v) {
n = lws_dll2_foreach_safe(&v->listen_wsi, arg, cb);
if (n)
return n;
v = v->vhost_next;
}
return 0;
}
#endif
/*
* Mark the vhost as being destroyed, so things trying to use it abort.
@ -1244,8 +1273,8 @@ lws_vhost_destroy1(struct lws_vhost *vh)
/*
* PHASE 1: take down or reassign any listen wsi
*
* Are there other vhosts that are piggybacking on our listen socket?
* If so we need to hand the listen socket off to one of the others
* Are there other vhosts that are piggybacking on our listen sockets?
* If so we need to hand each listen socket off to one of the others
* so it will remain open.
*
* If not, close the listen socket now.
@ -1254,15 +1283,21 @@ lws_vhost_destroy1(struct lws_vhost *vh)
* immediately performed.
*/
if (vh->lserv_wsi) {
lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
lws_dll2_get_head(&vh->listen_wsi)) {
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
/*
* For each of our listen sockets, check every other vhost to
* see if another vhost should be given our listen socket.
*
* ipv4 and ipv6 sockets will both match and be migrated.
*/
lws_start_foreach_ll(struct lws_vhost *, v,
context->vhost_list) {
if (v != vh &&
!v->being_destroyed &&
v->listen_port == vh->listen_port &&
((!v->iface && !vh->iface) ||
(v->iface && vh->iface &&
!strcmp(v->iface, vh->iface)))) {
if (v != vh && !v->being_destroyed &&
lws_vhost_compare_listen(v, vh)) {
/*
* this can only be a listen wsi, which is
* restricted... it has no protocol or other
@ -1275,31 +1310,32 @@ lws_vhost_destroy1(struct lws_vhost *vh)
__func__, lws_vh_tag(vh),
lws_vh_tag(v));
assert(v->lserv_wsi == NULL);
v->lserv_wsi = vh->lserv_wsi;
if (v->lserv_wsi) {
/* req cx + vh lock */
__lws_vhost_unbind_wsi(vh->lserv_wsi);
lws_vhost_bind_wsi(v, v->lserv_wsi);
vh->lserv_wsi = NULL;
}
lws_dll2_remove(&wsi->listen_list);
lws_dll2_add_tail(&wsi->listen_list,
&v->listen_wsi);
/* req cx + vh lock */
__lws_vhost_unbind_wsi(wsi);
lws_vhost_bind_wsi(v, wsi);
break;
}
} lws_end_foreach_ll(v, vhost_next);
if (vh->lserv_wsi) {
/*
* we didn't pass it off to another vhost on the same
* listen port... let's close it next time around the
* event loop without waiting for the logical destroy
* of the vhost itself
*/
lws_set_timeout(vh->lserv_wsi, 1, LWS_TO_KILL_ASYNC);
vh->lserv_wsi = NULL;
}
}
} lws_end_foreach_dll_safe(d, d1);
/*
* If any listen wsi left we couldn't pass to other vhosts, close them
*/
lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
lws_dll2_get_head(&vh->listen_wsi)) {
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
lws_dll2_remove(&wsi->listen_list);
lws_wsi_close(wsi, LWS_TO_KILL_ASYNC);
} lws_end_foreach_dll_safe(d, d1);
#endif
#if defined(LWS_WITH_TLS_JIT_TRUST)
lws_sul_cancel(&vh->sul_unref);
@ -1578,44 +1614,40 @@ lws_get_vhost_listen_port(struct lws_vhost *vhost)
#if defined(LWS_WITH_SERVER)
void
lws_context_deprecate(struct lws_context *context, lws_reload_func cb)
lws_context_deprecate(struct lws_context *cx, lws_reload_func cb)
{
struct lws_vhost *vh = context->vhost_list, *vh1;
struct lws_vhost *vh = cx->vhost_list;
/*
* "deprecation" means disable the context from accepting any new
* "deprecation" means disable the cx from accepting any new
* connections and free up listen sockets to be used by a replacement
* context.
* cx.
*
* Otherwise the deprecated context remains operational, until its
* Otherwise the deprecated cx remains operational, until its
* number of connected sockets falls to zero, when it is deleted.
*
* So, for each vhost, close his listen sockets
*/
/* for each vhost, close his listen socket */
while (vh) {
struct lws *wsi = vh->lserv_wsi;
if (wsi) {
lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
lws_dll2_get_head(&vh->listen_wsi)) {
struct lws *wsi = lws_container_of(d, struct lws,
listen_list);
wsi->socket_is_permanently_unusable = 1;
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "ctx deprecate");
wsi->a.context->deprecation_pending_listen_close_count++;
/*
* other vhosts can share the listen port, they
* point to the same wsi. So zap those too.
*/
vh1 = context->vhost_list;
while (vh1) {
if (vh1->lserv_wsi == wsi)
vh1->lserv_wsi = NULL;
vh1 = vh1->vhost_next;
}
}
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
__func__);
cx->deprecation_pending_listen_close_count++;
} lws_end_foreach_dll_safe(d, d1);
vh = vh->vhost_next;
}
context->deprecated = 1;
context->deprecation_cb = cb;
cx->deprecated = 1;
cx->deprecation_cb = cb;
}
#endif

View file

@ -293,12 +293,21 @@ elops_accept_glib(struct lws *wsi)
return 0;
}
static int
elops_listen_init_glib(struct lws_dll2 *d, void *user)
{
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
elops_accept_glib(wsi);
return 0;
}
static int
elops_init_pt_glib(struct lws_context *context, void *_loop, int tsi)
{
struct lws_context_per_thread *pt = &context->pt[tsi];
struct lws_pt_eventlibs_glib *ptpr = pt_to_priv_glib(pt);
struct lws_vhost *vh = context->vhost_list;
GMainLoop *loop = (GMainLoop *)_loop;
if (!loop)
@ -314,17 +323,7 @@ elops_init_pt_glib(struct lws_context *context, void *_loop, int tsi)
ptpr->loop = loop;
/*
* Initialize all events with the listening sockets
* and register a callback for read operations
*/
while (vh) {
if (vh->lserv_wsi)
elops_accept_glib(vh->lserv_wsi);
vh = vh->vhost_next;
}
lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_init_glib);
lws_glib_set_idle(pt);
@ -420,25 +419,26 @@ elops_destroy_wsi_glib(struct lws *wsi)
wsi_to_subclass(wsi) = NULL;
}
static int
elops_listen_destroy_glib(struct lws_dll2 *d, void *user)
{
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
elops_destroy_wsi_glib(wsi);
return 0;
}
static void
elops_destroy_pt_glib(struct lws_context *context, int tsi)
{
struct lws_context_per_thread *pt = &context->pt[tsi];
struct lws_pt_eventlibs_glib *ptpr = pt_to_priv_glib(pt);
struct lws_vhost *vh = context->vhost_list;
if (!pt_to_loop(pt))
return;
/*
* Free all events with the listening sockets
*/
while (vh) {
if (vh->lserv_wsi)
elops_destroy_wsi_glib(vh->lserv_wsi);
vh = vh->vhost_next;
}
lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_destroy_glib);
lws_gs_destroy(ptpr->idle);
lws_gs_destroy(ptpr->hrtimer);

View file

@ -133,6 +133,27 @@ lws_ev_sigint_cb(struct ev_loop *loop, struct ev_signal *watcher, int revents)
ev_break(loop, EVBREAK_ALL);
}
static int
elops_listen_init_ev(struct lws_dll2 *d, void *user)
{
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
struct lws_context *context = (struct lws_context *)user;
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt);
struct lws_wsi_eventlibs_libev *w = wsi_to_priv_ev(wsi);
struct lws_vhost *vh = wsi->a.vhost;
w->w_read.context = context;
w->w_write.context = context;
vh_to_priv_ev(vh)->w_accept.context = context;
ev_io_init(&vh_to_priv_ev(vh)->w_accept.watcher,
lws_accept_cb, wsi->desc.sockfd, EV_READ);
ev_io_start(ptpr->io_loop, &vh_to_priv_ev(vh)->w_accept.watcher);
return 0;
}
static int
elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
{
@ -140,7 +161,6 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt);
struct ev_signal *w_sigint = &ptpr->w_sigint.watcher;
struct ev_loop *loop = (struct ev_loop *)_loop;
struct lws_vhost *vh = context->vhost_list;
const char *backend_name;
unsigned int backend;
int status = 0;
@ -162,26 +182,7 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
ptpr->io_loop = loop;
/*
* Initialize the accept w_accept with all the listening sockets
* and register a callback for read operations
*/
while (vh) {
if (vh->lserv_wsi) {
struct lws_wsi_eventlibs_libev *w =
wsi_to_priv_ev(vh->lserv_wsi);
w->w_read.context = context;
w->w_write.context = context;
vh_to_priv_ev(vh)->w_accept.context = context;
ev_io_init(&vh_to_priv_ev(vh)->w_accept.watcher,
lws_accept_cb,
vh->lserv_wsi->desc.sockfd, EV_READ);
ev_io_start(loop, &vh_to_priv_ev(vh)->w_accept.watcher);
}
vh = vh->vhost_next;
}
lws_vhost_foreach_listen_wsi(context, context, elops_listen_init_ev);
/* Register the signal watcher unless it's a foreign loop */
if (!context->pt[tsi].event_loop_foreign) {
@ -236,19 +237,27 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
return status;
}
static int
elops_listen_destroy_ev(struct lws_dll2 *d, void *user)
{
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
struct lws_context *context = (struct lws_context *)user;
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt);
struct lws_vhost *vh = wsi->a.vhost;
ev_io_stop(ptpr->io_loop, &vh_to_priv_ev(vh)->w_accept.watcher);
return 0;
}
static void
elops_destroy_pt_ev(struct lws_context *context, int tsi)
{
struct lws_context_per_thread *pt = &context->pt[tsi];
struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt);
struct lws_vhost *vh = context->vhost_list;
while (vh) {
if (vh->lserv_wsi)
ev_io_stop(ptpr->io_loop,
&vh_to_priv_ev(vh)->w_accept.watcher);
vh = vh->vhost_next;
}
lws_vhost_foreach_listen_wsi(context, context, elops_listen_destroy_ev);
/* static assets */

View file

@ -175,6 +175,25 @@ lws_event_sigint_cb(evutil_socket_t sock_fd, short revents, void *ctx)
event_base_loopbreak(pt_to_priv_event(pt)->io_loop);
}
static int
elops_listen_init_event(struct lws_dll2 *d, void *user)
{
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
struct lws_context *context = (struct lws_context *)user;
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
struct lws_io_watcher_libevent *w_read =
&(wsi_to_priv_event(wsi)->w_read);
w_read->context = context;
w_read->watcher = event_new(ptpr->io_loop, wsi->desc.sockfd,
(EV_READ | EV_PERSIST), lws_event_cb, w_read);
event_add(w_read->watcher, NULL);
w_read->set = 1;
return 0;
}
static int
elops_init_pt_event(struct lws_context *context, void *_loop, int tsi)
{
@ -198,26 +217,7 @@ elops_init_pt_event(struct lws_context *context, void *_loop, int tsi)
ptpr->io_loop = loop;
/*
* Initialize all events with the listening sockets
* and register a callback for read operations
*/
while (vh) {
if (vh->lserv_wsi) {
struct lws_io_watcher_libevent *w_read =
&(wsi_to_priv_event(vh->lserv_wsi)->w_read);
w_read->context = context;
w_read->watcher = event_new(
loop, vh->lserv_wsi->desc.sockfd,
(EV_READ | EV_PERSIST), lws_event_cb,
w_read);
event_add(w_read->watcher, NULL);
w_read->set = 1;
}
vh = vh->vhost_next;
}
lws_vhost_foreach_listen_wsi(context, context, elops_listen_init_event);
/* static event loop objects */
@ -334,6 +334,23 @@ elops_run_pt_event(struct lws_context *context, int tsi)
pt_to_priv_event(&context->pt[tsi])->io_loop);
}
static int
elops_listen_destroy_event(struct lws_dll2 *d, void *user)
{
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
struct lws_context *context = (struct lws_context *)user;
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
struct lws_wsi_eventlibs_libevent *w = wsi_to_priv_event(wsi);
event_free(w->w_read.watcher);
w->w_read.watcher = NULL;
event_free(w->w_write.watcher);
w->w_write.watcher = NULL;
return 0;
}
static void
elops_destroy_pt_event(struct lws_context *context, int tsi)
{
@ -346,21 +363,7 @@ elops_destroy_pt_event(struct lws_context *context, int tsi)
if (!ptpr->io_loop)
return;
/*
* Free all events with the listening sockets
*/
while (vh) {
if (vh->lserv_wsi) {
struct lws_wsi_eventlibs_libevent *w =
wsi_to_priv_event(vh->lserv_wsi);
event_free(w->w_read.watcher);
w->w_read.watcher = NULL;
event_free(w->w_write.watcher);
w->w_write.watcher = NULL;
}
vh = vh->vhost_next;
}
lws_vhost_foreach_listen_wsi(context, context, elops_listen_destroy_event);
event_free(ptpr->hrtimer);
event_free(ptpr->idle_timer);

View file

@ -677,6 +677,17 @@ elops_destroy_pt_uv(struct lws_context *context, int tsi)
uv_close((uv_handle_t *)&pt_to_priv_uv(pt)->idle, lws_uv_close_cb_sa);
}
static int
elops_listen_init_uv(struct lws_dll2 *d, void *user)
{
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
if (elops_init_vhost_listen_wsi_uv(wsi) == -1)
return -1;
return 0;
}
/*
* This needs to be called after vhosts have been defined.
*
@ -689,7 +700,6 @@ elops_init_pt_uv(struct lws_context *context, void *_loop, int tsi)
{
struct lws_context_per_thread *pt = &context->pt[tsi];
struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt);
struct lws_vhost *vh = context->vhost_list;
int status = 0, n, ns, first = 1;
uv_loop_t *loop = (uv_loop_t *)_loop;
@ -745,11 +755,7 @@ elops_init_pt_uv(struct lws_context *context, void *_loop, int tsi)
* We have to do it here because the uv loop(s) are not
* initialized until after context creation.
*/
while (vh) {
if (elops_init_vhost_listen_wsi_uv(vh->lserv_wsi) == -1)
return -1;
vh = vh->vhost_next;
}
lws_vhost_foreach_listen_wsi(context, context, elops_listen_init_uv);
if (!first)
return status;

View file

@ -231,18 +231,28 @@ init_vhost_listen_wsi_sd(struct lws *wsi)
return 0;
}
static int
elops_listen_init_sdevent(struct lws_dll2 *d, void *user)
{
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
if (init_vhost_listen_wsi_sd(wsi) == -1)
return -1;
return 0;
}
static int
init_pt_sd(struct lws_context *context, void *_loop, int tsi)
{
struct lws_context_per_thread *pt = &context->pt[tsi];
struct lws_pt_eventlibs_sdevent *ptpriv = pt_to_priv_sd(pt);
struct sd_event *loop = (struct sd_event *)_loop;
struct lws_vhost *vh;
int first = 1; // we are the first that create and initialize the loop
int first = 1; /* first to create and initialize the loop */
ptpriv->pt = pt;
// make sure we have an event loop
/* make sure we have an event loop */
if (!ptpriv->io_loop) {
if (!loop) {
if (sd_event_default(&loop) < 0) {
@ -257,7 +267,6 @@ init_pt_sd(struct lws_context *context, void *_loop, int tsi)
}
ptpriv->io_loop = loop;
} else
/*
* If the loop was initialized before, we do not need to
@ -265,12 +274,7 @@ init_pt_sd(struct lws_context *context, void *_loop, int tsi)
*/
first = 0;
// initialize accept/read for vhosts
// Note: default vhost usually not included here
for (vh = context->vhost_list; vh; vh = vh->vhost_next)
/* call lws_event_loop_ops->init_vhost_listen_wsi */
if (init_vhost_listen_wsi_sd(vh->lserv_wsi) == -1)
return -1;
lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_init_sdevent);
if (first) {
@ -361,16 +365,23 @@ run_pt_sd(struct lws_context *context, int tsi)
sd_event_run(ptpriv->io_loop, (uint64_t) -1);
}
static int
elops_listen_destroy_sdevent(struct lws_dll2 *d, void *user)
{
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
wsi_logical_close_sd(wsi);
return 0;
}
static void
destroy_pt_sd(struct lws_context *context, int tsi)
{
struct lws_context_per_thread *pt = &context->pt[tsi];
struct lws_pt_eventlibs_sdevent *ptpriv = pt_to_priv_sd(pt);
struct lws_vhost *vh;
for (vh = context->vhost_list; vh; vh = vh->vhost_next)
if (vh->lserv_wsi)
wsi_logical_close_sd(vh->lserv_wsi);
lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_destroy_sdevent);
if (ptpriv->sultimer) {
sd_event_source_set_enabled(ptpriv->sultimer,
@ -390,7 +401,6 @@ destroy_pt_sd(struct lws_context *context, int tsi)
sd_event_unref(ptpriv->io_loop);
ptpriv->io_loop = NULL;
}
}
const struct lws_event_loop_ops event_loop_ops_sdevent = {

View file

@ -132,33 +132,30 @@ lws_uloop_cb(struct uloop_fd *ufd, unsigned int revents)
uloop_timeout_set(&pt_to_priv_uloop(pt)->idle_timer, 1);
}
static int
elops_listen_init_uloop(struct lws_dll2 *d, void *user)
{
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
struct lws_wsi_eventlibs_uloop *wu = wsi_to_priv_uloop(wsi);
wu->wsi = wsi;
wu->fd.fd = wsi->desc.sockfd;
wu->fd.cb = lws_uloop_cb;
uloop_fd_add(&wu->fd, ULOOP_READ);
wu->actual_events = ULOOP_READ;
return 0;
}
static int
elops_init_pt_uloop(struct lws_context *context, void *v, int tsi)
{
struct lws_vhost *vh = context->vhost_list;
struct lws_context_per_thread *pt = &context->pt[tsi];
struct lws_pt_eventlibs_uloop *ptpr = pt_to_priv_uloop(pt);
ptpr->pt = pt;
/*
* Initialize all events with the listening sockets
* and register a callback for read operations
*/
while (vh) {
if (vh->lserv_wsi) {
struct lws_wsi_eventlibs_uloop *wu =
wsi_to_priv_uloop(vh->lserv_wsi);
wu->wsi = vh->lserv_wsi;
wu->fd.fd = vh->lserv_wsi->desc.sockfd;
wu->fd.cb = lws_uloop_cb;
uloop_fd_add(&wu->fd, ULOOP_READ);
wu->actual_events = ULOOP_READ;
}
vh = vh->vhost_next;
}
lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_init_uloop);
/* static event loop objects */
@ -217,20 +214,24 @@ elops_run_pt_uloop(struct lws_context *context, int tsi)
uloop_run();
}
static int
elops_listen_destroy_uloop(struct lws_dll2 *d, void *user)
{
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
struct lws_wsi_eventlibs_uloop *wu = wsi_to_priv_uloop(wsi);
uloop_fd_delete(&wu->fd);
return 0;
}
static void
elops_destroy_pt_uloop(struct lws_context *context, int tsi)
{
struct lws_context_per_thread *pt = &context->pt[tsi];
struct lws_pt_eventlibs_uloop *ptpr = pt_to_priv_uloop(pt);
struct lws_vhost *vh;
vh = context->vhost_list;
while (vh) {
if (vh->lserv_wsi)
uloop_fd_delete(&wsi_to_priv_uloop(vh->lserv_wsi)->fd);
vh = vh->vhost_next;
}
lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_destroy_uloop);
uloop_timeout_cancel(&ptpr->hrtimer);
uloop_timeout_cancel(&ptpr->idle_timer);

View file

@ -80,18 +80,15 @@ _lws_vhost_init_server(const struct lws_context_creation_info *info,
vhost->listen_port == CONTEXT_PORT_NO_LISTEN_SERVER)
return 0;
vh = vhost->context->vhost_list;
while (vh) {
if (vh->listen_port == vhost->listen_port) {
if (((!vhost->iface && !vh->iface) ||
(vhost->iface && vh->iface &&
!strcmp(vhost->iface, vh->iface))) &&
vh->lserv_wsi
) {
lwsl_notice(" using listen skt from vhost %s\n",
vh->name);
return 0;
}
if (vh->listen_wsi.count &&
lws_vhost_compare_listen(vhost, vh)) {
lwsl_notice(" using listen skt from vhost %s\n",
vh->name);
return 0;
}
vh = vh->vhost_next;
}
@ -346,7 +343,7 @@ done_list:
goto bail;
}
vhost->lserv_wsi = wsi;
lws_dll2_add_tail(&wsi->listen_list, &vhost->listen_wsi);
lws_pt_unlock(pt);
#if defined(WIN32) && defined(TCP_FASTOPEN)
@ -375,7 +372,7 @@ done_list:
n = listen(wsi->desc.sockfd, LWS_SOMAXCONN);
if (n < 0) {
lwsl_err("listen failed with error %d\n", LWS_ERRNO);
vhost->lserv_wsi = NULL;
lws_dll2_remove(&wsi->listen_list);
__remove_wsi_socket_from_fds(wsi);
goto bail;
}

View file

@ -205,10 +205,17 @@ lws_gate_accepts(struct lws_context *context, int on)
lwsl_notice("%s: on = %d\n", __func__, on);
while (v) {
if (v->tls.use_ssl && v->lserv_wsi &&
lws_change_pollfd(v->lserv_wsi, (LWS_POLLIN) * !on,
(LWS_POLLIN) * on))
lwsl_notice("Unable to set accept POLLIN %d\n", on);
lws_start_foreach_dll(struct lws_dll2 *, d,
lws_dll2_get_head(&v->listen_wsi)) {
struct lws *wsi = lws_container_of(d, struct lws,
listen_list);
if (v->tls.use_ssl &&
lws_change_pollfd(wsi, on ? 0 : LWS_POLLIN,
on ? LWS_POLLIN : 0))
lwsl_notice("%s: Unable to set POLLIN %d\n",
__func__, on);
} lws_end_foreach_dll(d);
v = v->vhost_next;
}