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:
parent
8c122cd8bd
commit
6163c96727
14 changed files with 295 additions and 214 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue