mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
eventlib: add sd-event support
This commit is contained in:
parent
77055c4fd7
commit
b961e5f351
16 changed files with 610 additions and 5 deletions
|
@ -195,6 +195,10 @@
|
|||
"libglib": {
|
||||
"cmake": "-DLWS_WITH_GLIB=ON"
|
||||
},
|
||||
"sdevent": {
|
||||
"cmake": "-DLWS_WITH_SDEVENT=ON",
|
||||
"platforms": "none, linux-fedora-32/x86_64-amd/gcc"
|
||||
},
|
||||
"ipv6": {
|
||||
"cmake": "-DLWS_IPV6=ON",
|
||||
"platforms": "windows-10/x86_64-amd/mingw64, windows-10/x86_64-amd/msvc"
|
||||
|
|
|
@ -118,7 +118,8 @@ endif()
|
|||
if (LWS_WITH_LIBEV OR
|
||||
LWS_WITH_LIBUV OR
|
||||
LWS_WITH_LIBEVENT OR
|
||||
LWS_WITH_GLIB)
|
||||
LWS_WITH_GLIB OR
|
||||
LWS_WITH_SDEVENT)
|
||||
set(LWS_WITH_EVENT_LIBS 1)
|
||||
else()
|
||||
unset(LWS_WITH_EVENT_LIBS)
|
||||
|
|
|
@ -171,6 +171,7 @@ option(LWS_WITH_LIBEV "Compile with support for libev" OFF)
|
|||
option(LWS_WITH_LIBUV "Compile with support for libuv" OFF)
|
||||
option(LWS_WITH_LIBEVENT "Compile with support for libevent" OFF)
|
||||
option(LWS_WITH_GLIB "Compile with support for glib event loop" OFF)
|
||||
option(LWS_WITH_SDEVENT "Compile with support for sd-event loop" OFF)
|
||||
|
||||
if (UNIX)
|
||||
# since v4.1, on unix platforms default is build any event libs as runtime plugins
|
||||
|
|
|
@ -152,6 +152,7 @@
|
|||
#cmakedefine LWS_WITH_LIBEV
|
||||
#cmakedefine LWS_WITH_LIBEVENT
|
||||
#cmakedefine LWS_WITH_LIBUV
|
||||
#cmakedefine LWS_WITH_SDEVENT
|
||||
#cmakedefine LWS_WITH_LWSAC
|
||||
#cmakedefine LWS_LOGS_TIMESTAMP
|
||||
#cmakedefine LWS_WITH_MBEDTLS
|
||||
|
|
|
@ -233,6 +233,10 @@
|
|||
#define LWS_SERVER_OPTION_SS_PROXY (1ll << 36)
|
||||
/**< (VH) We are being a SS Proxy listen socket for the vhost */
|
||||
|
||||
#define LWS_SERVER_OPTION_SDEVENT (1ll << 37)
|
||||
/**< (CTX) Use sd-event loop */
|
||||
|
||||
|
||||
/****** add new things just above ---^ ******/
|
||||
|
||||
|
||||
|
|
|
@ -369,6 +369,7 @@ static const struct lws_evlib_map {
|
|||
{ LWS_SERVER_OPTION_LIBEVENT, "evlib_event" },
|
||||
{ LWS_SERVER_OPTION_GLIB, "evlib_glib" },
|
||||
{ LWS_SERVER_OPTION_LIBEV, "evlib_ev" },
|
||||
{ LWS_SERVER_OPTION_SDEVENT, "evlib_sd" },
|
||||
};
|
||||
static const char * const dlist[] = {
|
||||
".", /* Priority 1: plugins in cwd */
|
||||
|
@ -598,6 +599,13 @@ lws_create_context(const struct lws_context_creation_info *info)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_SDEVENT)
|
||||
if (lws_check_opt(info->options, LWS_SERVER_OPTION_SDEVENT)) {
|
||||
extern const lws_plugin_evlib_t evlib_sd;
|
||||
plev = &evlib_sd;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* with event libs */
|
||||
|
||||
#endif /* not with ev plugins */
|
||||
|
|
|
@ -92,6 +92,10 @@ if (LWS_WITH_LIBEV)
|
|||
set(LWS_HAVE_EVBACKEND_IOURING ${LWS_HAVE_EVBACKEND_IOURING} PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_SDEVENT)
|
||||
add_subdir_include_directories(sdevent)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
#
|
||||
|
|
|
@ -8,7 +8,7 @@ and native WSA on windows.
|
|||
To get access to epoll() or other platform specific better poll waits, or to
|
||||
integrate with existing applications already using a specific event loop, it can
|
||||
be desirable for lws to use another external event library, like libuv, glib,
|
||||
libevent or libev.
|
||||
libevent, libev, or sdevent.
|
||||
|
||||
Lws supports wholesale replacement of its wait selectable at runtime, either by
|
||||
building support for one or more event lib into the libwebsockets library, or by
|
||||
|
|
44
lib/event-libs/sdevent/CMakeLists.txt
Normal file
44
lib/event-libs/sdevent/CMakeLists.txt
Normal file
|
@ -0,0 +1,44 @@
|
|||
# The strategy is to only export to PARENT_SCOPE
|
||||
#
|
||||
# - changes to LIB_LIST
|
||||
# - includes via include_directories
|
||||
#
|
||||
# and keep everything else private
|
||||
|
||||
include_directories(.)
|
||||
|
||||
# configure or find systemd library
|
||||
set(LIB_SYSTEMD_LIBRARIES CACHE PATH "Path to the libsystemd library")
|
||||
if ("${LWS_SYSTEMD_LIBRARIES}" STREQUAL "")
|
||||
if (NOT LIB_SYSTEMD_FOUND)
|
||||
find_path(LIBSYSTEMD_INCLUDE_DIRS NAMES systemd/sd-event.h)
|
||||
find_library(LIBSYSTEMD_LIBRARIES NAMES systemd)
|
||||
endif()
|
||||
else()
|
||||
set(LIBSYSTEMD_LIBRARIES ${LWS_SYSTEMD_LIBRARIES})
|
||||
set(LIBSYSTEMD_INCLUDE_DIRS ${LWS_LIBSYSTEMD_INCLUDE_DIRS})
|
||||
endif()
|
||||
message("libsystemd include dir: ${LIBSYSTEMD_INCLUDE_DIRS}")
|
||||
message("libsystemd libraries: ${LIBSYSTEMD_LIBRARIES}")
|
||||
|
||||
if (LWS_WITH_EVLIB_PLUGINS)
|
||||
|
||||
create_evlib_plugin(
|
||||
evlib_sd
|
||||
sdevent.c
|
||||
private-lib-event-libs-sdevent.h
|
||||
${LIBSYSTEMD_LIBRARIES}
|
||||
)
|
||||
|
||||
else()
|
||||
|
||||
list(APPEND LIB_LIST ${LIBSYSTEMD_LIBRARIES})
|
||||
list(APPEND SOURCES event-libs/sdevent/sdevent.c)
|
||||
|
||||
endif()
|
||||
|
||||
#
|
||||
# Keep explicit parent scope exports at end
|
||||
#
|
||||
|
||||
exports_to_parent_scope()
|
3
lib/event-libs/sdevent/private-lib-event-libs-sdevent.h
Normal file
3
lib/event-libs/sdevent/private-lib-event-libs-sdevent.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
#include <private-lib-core.h>
|
||||
|
||||
extern const struct lws_event_loop_ops event_loop_ops_sdevent;
|
431
lib/event-libs/sdevent/sdevent.c
Normal file
431
lib/event-libs/sdevent/sdevent.c
Normal file
|
@ -0,0 +1,431 @@
|
|||
#include <systemd/sd-event.h>
|
||||
|
||||
#include <private-lib-core.h>
|
||||
#include "private-lib-event-libs-sdevent.h"
|
||||
|
||||
#define pt_to_priv_sd(_pt) ((struct lws_pt_eventlibs_sdevent *)(_pt)->evlib_pt)
|
||||
#define wsi_to_priv_sd(_w) ((struct lws_wsi_watcher_sdevent *)(_w)->evlib_wsi)
|
||||
|
||||
struct lws_pt_eventlibs_sdevent {
|
||||
struct lws_context_per_thread *pt;
|
||||
struct sd_event *io_loop;
|
||||
struct sd_event_source *sultimer;
|
||||
struct sd_event_source *idletimer;
|
||||
};
|
||||
|
||||
struct lws_wsi_watcher_sdevent {
|
||||
struct sd_event_source *source;
|
||||
uint32_t events;
|
||||
};
|
||||
|
||||
static int
|
||||
sultimer_handler(sd_event_source *s, uint64_t usec, void *userdata)
|
||||
{
|
||||
struct lws_context_per_thread *pt = (struct lws_context_per_thread *)userdata;
|
||||
|
||||
lws_usec_t us;
|
||||
|
||||
lws_context_lock(pt->context, __func__);
|
||||
lws_pt_lock(pt, __func__);
|
||||
|
||||
us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
|
||||
lws_now_usecs());
|
||||
if (us) {
|
||||
uint64_t at;
|
||||
|
||||
sd_event_now(sd_event_source_get_event(s), CLOCK_MONOTONIC, &at);
|
||||
at += (uint64_t)us;
|
||||
sd_event_source_set_time(pt_to_priv_sd(pt)->sultimer, at);
|
||||
sd_event_source_set_enabled(pt_to_priv_sd(pt)->sultimer,
|
||||
SD_EVENT_ONESHOT);
|
||||
}
|
||||
|
||||
lws_pt_unlock(pt);
|
||||
lws_context_unlock(pt->context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
idle_handler(sd_event_source *s, uint64_t usec, void *userdata)
|
||||
{
|
||||
struct lws_context_per_thread *pt = (struct lws_context_per_thread *)userdata;
|
||||
|
||||
lws_usec_t us;
|
||||
|
||||
lws_service_do_ripe_rxflow(pt);
|
||||
|
||||
lws_context_lock(pt->context, __func__);
|
||||
lws_pt_lock(pt, __func__);
|
||||
|
||||
/*
|
||||
* is there anybody with pending stuff that needs service forcing?
|
||||
*/
|
||||
if (!lws_service_adjust_timeout(pt->context, 1, pt->tid))
|
||||
/* -1 timeout means just do forced service */
|
||||
_lws_plat_service_forced_tsi(pt->context, pt->tid);
|
||||
|
||||
/* account for sultimer */
|
||||
|
||||
us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
|
||||
lws_now_usecs());
|
||||
|
||||
if (us) {
|
||||
uint64_t at;
|
||||
|
||||
sd_event_now(sd_event_source_get_event(s), CLOCK_MONOTONIC, &at);
|
||||
at += (uint64_t)us;
|
||||
sd_event_source_set_time(pt_to_priv_sd(pt)->sultimer, at);
|
||||
sd_event_source_set_enabled(pt_to_priv_sd(pt)->sultimer,
|
||||
SD_EVENT_ONESHOT);
|
||||
}
|
||||
|
||||
sd_event_source_set_enabled(pt_to_priv_sd(pt)->idletimer, SD_EVENT_OFF);
|
||||
|
||||
lws_pt_unlock(pt);
|
||||
lws_context_unlock(pt->context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sock_accept_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata)
|
||||
{
|
||||
struct lws *wsi = (struct lws *)userdata;
|
||||
struct lws_context *context = wsi->a.context;
|
||||
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
|
||||
struct sd_event_source *idletimer, *watcher;
|
||||
struct lws_pollfd eventfd;
|
||||
|
||||
lws_context_lock(pt->context, __func__);
|
||||
lws_pt_lock(pt, __func__);
|
||||
|
||||
if (pt->is_destroyed)
|
||||
goto bail;
|
||||
|
||||
eventfd.fd = fd;
|
||||
eventfd.events = 0;
|
||||
eventfd.revents = 0;
|
||||
|
||||
if (revents & EPOLLIN) {
|
||||
eventfd.events |= LWS_POLLIN;
|
||||
eventfd.revents |= LWS_POLLIN;
|
||||
}
|
||||
|
||||
if (revents & EPOLLOUT) {
|
||||
eventfd.events |= LWS_POLLOUT;
|
||||
eventfd.revents |= LWS_POLLOUT;
|
||||
}
|
||||
|
||||
lws_pt_unlock(pt);
|
||||
lws_context_unlock(pt->context);
|
||||
|
||||
lws_service_fd_tsi(context, &eventfd, wsi->tsi);
|
||||
|
||||
if (pt->destroy_self) {
|
||||
lws_context_destroy(pt->context);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* fire idle handler */
|
||||
idletimer = pt_to_priv_sd(pt)->idletimer;
|
||||
if (idletimer) {
|
||||
sd_event_source_set_time(idletimer, (uint64_t) 0);
|
||||
sd_event_source_set_enabled(idletimer, SD_EVENT_ON);
|
||||
}
|
||||
|
||||
/*
|
||||
* allow further events
|
||||
*
|
||||
* Note:
|
||||
* do not move the assignment up, lws_service_fd_tsi may invalidate it!
|
||||
*/
|
||||
watcher = wsi_to_priv_sd(wsi)->source;
|
||||
if (watcher)
|
||||
sd_event_source_set_enabled(watcher, SD_EVENT_ONESHOT);
|
||||
|
||||
return 0;
|
||||
|
||||
bail:
|
||||
lws_pt_unlock(pt);
|
||||
lws_context_unlock(pt->context);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
io_sd(struct lws *wsi, unsigned int flags)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
|
||||
|
||||
/*
|
||||
* Only manipulate if there is an event source, and if
|
||||
* the pt is still alive
|
||||
*/
|
||||
if (!pt_to_priv_sd(pt)->io_loop ||
|
||||
!wsi_to_priv_sd(wsi)->source ||
|
||||
pt->is_destroyed)
|
||||
return;
|
||||
|
||||
// assert that the requested flags do not contain anything unexpected
|
||||
if (!((flags & (LWS_EV_START | LWS_EV_STOP)) &&
|
||||
(flags & (LWS_EV_READ | LWS_EV_WRITE)))) {
|
||||
lwsl_err("%s: assert: flags %d", __func__, flags);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
// we are overdoing a bit here, so it resembles the structure in libuv.c
|
||||
if (flags & LWS_EV_START) {
|
||||
if (flags & LWS_EV_WRITE)
|
||||
wsi_to_priv_sd(wsi)->events |= EPOLLOUT;
|
||||
|
||||
if (flags & LWS_EV_READ)
|
||||
wsi_to_priv_sd(wsi)->events |= EPOLLIN;
|
||||
|
||||
sd_event_source_set_io_events(wsi_to_priv_sd(wsi)->source,
|
||||
wsi_to_priv_sd(wsi)->events);
|
||||
sd_event_source_set_enabled(wsi_to_priv_sd(wsi)->source,
|
||||
SD_EVENT_ONESHOT);
|
||||
} else {
|
||||
if (flags & LWS_EV_WRITE)
|
||||
wsi_to_priv_sd(wsi)->events =
|
||||
wsi_to_priv_sd(wsi)->events &
|
||||
(uint32_t)(~EPOLLOUT);
|
||||
|
||||
if (flags & LWS_EV_READ)
|
||||
wsi_to_priv_sd(wsi)->events =
|
||||
wsi_to_priv_sd(wsi)->events &
|
||||
(uint32_t)(~EPOLLIN);
|
||||
|
||||
sd_event_source_set_io_events(wsi_to_priv_sd(wsi)->source,
|
||||
wsi_to_priv_sd(wsi)->events);
|
||||
|
||||
if (!(wsi_to_priv_sd(wsi)->events & (EPOLLIN | EPOLLOUT)))
|
||||
sd_event_source_set_enabled(wsi_to_priv_sd(wsi)->source,
|
||||
SD_EVENT_ONESHOT);
|
||||
else
|
||||
sd_event_source_set_enabled(wsi_to_priv_sd(wsi)->source,
|
||||
SD_EVENT_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
init_vhost_listen_wsi_sd(struct lws *wsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt;
|
||||
|
||||
if (!wsi)
|
||||
return 0;
|
||||
|
||||
pt = &wsi->a.context->pt[(int)wsi->tsi];
|
||||
|
||||
sd_event_add_io(pt_to_priv_sd(pt)->io_loop,
|
||||
&wsi_to_priv_sd(wsi)->source,
|
||||
wsi->desc.sockfd,
|
||||
wsi_to_priv_sd(wsi)->events,
|
||||
sock_accept_handler,
|
||||
wsi);
|
||||
|
||||
io_sd(wsi, LWS_EV_START | LWS_EV_READ);
|
||||
|
||||
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
|
||||
|
||||
ptpriv->pt = pt;
|
||||
|
||||
// make sure we have an event loop
|
||||
if (!ptpriv->io_loop) {
|
||||
if (!loop) {
|
||||
if (sd_event_default(&loop) < 0) {
|
||||
lwsl_err("%s: sd_event_default failed\n", __func__);
|
||||
|
||||
return -1;
|
||||
}
|
||||
pt->event_loop_foreign = 0;
|
||||
} else {
|
||||
sd_event_ref(loop);
|
||||
pt->event_loop_foreign = 1;
|
||||
}
|
||||
|
||||
ptpriv->io_loop = loop;
|
||||
|
||||
} else
|
||||
/*
|
||||
* If the loop was initialized before, we do not need to
|
||||
* do full initialization
|
||||
*/
|
||||
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;
|
||||
|
||||
if (first) {
|
||||
|
||||
if (0 > sd_event_add_time(loop,
|
||||
&ptpriv->sultimer,
|
||||
CLOCK_MONOTONIC,
|
||||
UINT64_MAX,
|
||||
0,
|
||||
sultimer_handler,
|
||||
(void*) pt
|
||||
))
|
||||
return -1;
|
||||
|
||||
if (0 > sd_event_add_time(loop,
|
||||
&ptpriv->idletimer,
|
||||
CLOCK_MONOTONIC,
|
||||
0,
|
||||
0,
|
||||
idle_handler,
|
||||
(void *)pt))
|
||||
return -1;
|
||||
|
||||
sd_event_source_set_enabled(ptpriv->idletimer, SD_EVENT_ON);
|
||||
|
||||
if (0 > sd_event_source_set_priority(ptpriv->idletimer,
|
||||
SD_EVENT_PRIORITY_IDLE))
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
wsi_destroy_sd(struct lws *wsi)
|
||||
{
|
||||
if (!wsi)
|
||||
return;
|
||||
|
||||
io_sd(wsi, LWS_EV_STOP | (LWS_EV_READ | LWS_EV_WRITE));
|
||||
|
||||
if (wsi_to_priv_sd(wsi)->source) {
|
||||
sd_event_source_set_enabled(wsi_to_priv_sd(wsi)->source,
|
||||
SD_EVENT_OFF);
|
||||
sd_event_source_unref(wsi_to_priv_sd(wsi)->source);
|
||||
wsi_to_priv_sd(wsi)->source = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
wsi_logical_close_sd(struct lws *wsi)
|
||||
{
|
||||
wsi_destroy_sd(wsi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sock_accept_sd(struct lws *wsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
|
||||
|
||||
if (wsi->role_ops->file_handle)
|
||||
sd_event_add_io(pt_to_priv_sd(pt)->io_loop,
|
||||
&wsi_to_priv_sd(wsi)->source,
|
||||
wsi->desc.filefd,
|
||||
wsi_to_priv_sd(wsi)->events,
|
||||
sock_accept_handler,
|
||||
wsi);
|
||||
else
|
||||
sd_event_add_io(pt_to_priv_sd(pt)->io_loop,
|
||||
&wsi_to_priv_sd(wsi)->source,
|
||||
wsi->desc.sockfd,
|
||||
wsi_to_priv_sd(wsi)->events,
|
||||
sock_accept_handler,
|
||||
wsi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
run_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);
|
||||
|
||||
if (ptpriv->io_loop)
|
||||
sd_event_run(ptpriv->io_loop, (uint64_t) -1);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (ptpriv->sultimer) {
|
||||
sd_event_source_set_enabled(ptpriv->sultimer,
|
||||
SD_EVENT_OFF);
|
||||
sd_event_source_unref(ptpriv->sultimer);
|
||||
ptpriv->sultimer = NULL;
|
||||
}
|
||||
|
||||
if (ptpriv->idletimer) {
|
||||
sd_event_source_set_enabled(ptpriv->idletimer,
|
||||
SD_EVENT_OFF);
|
||||
sd_event_source_unref(ptpriv->idletimer);
|
||||
ptpriv->idletimer = NULL;
|
||||
}
|
||||
|
||||
if (ptpriv->io_loop) {
|
||||
sd_event_unref(ptpriv->io_loop);
|
||||
ptpriv->io_loop = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const struct lws_event_loop_ops event_loop_ops_sdevent = {
|
||||
.name = "sdevent",
|
||||
.init_context = NULL,
|
||||
.destroy_context1 = NULL,
|
||||
.destroy_context2 = NULL,
|
||||
.init_vhost_listen_wsi = init_vhost_listen_wsi_sd,
|
||||
.init_pt = init_pt_sd,
|
||||
.wsi_logical_close = wsi_logical_close_sd,
|
||||
.check_client_connect_ok = NULL,
|
||||
.close_handle_manually = NULL,
|
||||
.sock_accept = sock_accept_sd,
|
||||
.io = io_sd,
|
||||
.run_pt = run_pt_sd,
|
||||
.destroy_pt = destroy_pt_sd,
|
||||
.destroy_wsi = wsi_destroy_sd,
|
||||
|
||||
.flags = 0,
|
||||
|
||||
.evlib_size_ctx = 0,
|
||||
.evlib_size_pt = sizeof(struct lws_pt_eventlibs_sdevent),
|
||||
.evlib_size_vh = 0,
|
||||
.evlib_size_wsi = sizeof(struct lws_wsi_watcher_sdevent),
|
||||
};
|
||||
|
||||
#if defined(LWS_WITH_EVLIB_PLUGINS)
|
||||
LWS_VISIBLE
|
||||
#endif
|
||||
const lws_plugin_evlib_t evlib_sd = {
|
||||
.hdr = {
|
||||
"systemd event loop",
|
||||
"lws_evlib_plugin",
|
||||
LWS_PLUGIN_API_MAGIC
|
||||
},
|
||||
|
||||
.ops = &event_loop_ops_sdevent
|
||||
};
|
|
@ -19,7 +19,7 @@ CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defin
|
|||
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(LWS_WITH_LIBEVENT)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_LIBEVENT)
|
||||
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(LWS_WITH_LIBEV)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_LIBEV)
|
||||
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(LWS_WITH_GLIB)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_GLIB)
|
||||
|
||||
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(LWS_WITH_SDEVENT)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_SDEVENT)
|
||||
|
||||
if (LWS_WITH_LIBUV)
|
||||
find_path(LIBUV_INCLUDE_DIRS NAMES uv.h)
|
||||
|
@ -72,6 +72,16 @@ if (LWS_WITH_GLIB)
|
|||
set(extralibs ${extralibs} ${GLIB_LIBRARIES})
|
||||
list(APPEND SRCS glib.c)
|
||||
endif()
|
||||
if (LWS_WITH_SDEVENT)
|
||||
find_path(LIBSYSTEMD_INCLUDE_DIRS NAMES systemd/sd-event.h)
|
||||
find_library(LIBSYSTEMD_LIBRARIES NAMES systemd)
|
||||
message("libsystemd include dir: ${LIBSYSTEMD_INCLUDE_DIRS}")
|
||||
message("libsystemd libraries: ${LIBSYSTEMD_LIBRARIES}")
|
||||
include_directories("${LIBSYSTEMD_INCLUDE_DIRS}")
|
||||
set(extralibs ${extralibs} ${LIBSYSTEMD_LIBRARIES})
|
||||
list(APPEND SRCS libsdevent.c)
|
||||
endif()
|
||||
|
||||
|
||||
message("Extra libs: ${extralibs}")
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ Commandline option|Meaning
|
|||
--uv|Use the libuv event library (lws must have been configured with `-DLWS_WITH_LIBUV=1`)
|
||||
--event|Use the libevent library (lws must have been configured with `-DLWS_WITH_LIBEVENT=1`)
|
||||
--ev|Use the libev event library (lws must have been configured with `-DLWS_WITH_LIBEV=1`)
|
||||
--sd|Use the systemd event library (lws must have been configured with `-DLWS_WITH_SDEVENT=1`)
|
||||
|
||||
Notice libevent and libev cannot coexist in the one library. But all the other combinations are OK.
|
||||
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* lws-minimal-http-server-eventlib-foreign
|
||||
*
|
||||
* Written in 2020 by Christian Fuchs <christian.fuchs@scs.ch>
|
||||
*
|
||||
* This file is made available under the Creative Commons CC0 1.0
|
||||
* Universal Public Domain Dedication.
|
||||
*
|
||||
* The sdevent specific code
|
||||
*/
|
||||
|
||||
#include <libwebsockets.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <systemd/sd-event.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
static struct sd_event *sd_loop;
|
||||
static sd_event_source *sd_timer;
|
||||
static sd_event_source *sd_signal;
|
||||
|
||||
static int
|
||||
timer_cb_sd(sd_event_source *source, uint64_t now, void *user)
|
||||
{
|
||||
foreign_timer_service(sd_loop);
|
||||
|
||||
if (sd_timer) {
|
||||
sd_event_source_set_time(sd_timer, now + 1000000);
|
||||
sd_event_source_set_enabled(sd_timer, SD_EVENT_ON);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
signal_cb_sd(sd_event_source *source, const struct signalfd_siginfo *si,
|
||||
void *user)
|
||||
{
|
||||
signal_cb((int)si->ssi_signo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
foreign_event_loop_init_and_run_libsdevent(void)
|
||||
{
|
||||
uint64_t now;
|
||||
|
||||
/* we create and start our "foreign loop" */
|
||||
|
||||
sd_event_default(&sd_loop);
|
||||
sd_event_add_signal(sd_loop, &sd_signal, SIGINT, signal_cb_sd, NULL);
|
||||
|
||||
sd_event_now(sd_loop, CLOCK_MONOTONIC, &now);
|
||||
sd_event_add_time(sd_loop, &sd_timer, CLOCK_MONOTONIC, now,
|
||||
(uint64_t) 1000, timer_cb_sd, NULL);
|
||||
|
||||
sd_event_loop(sd_loop);
|
||||
}
|
||||
|
||||
static void
|
||||
foreign_event_loop_stop_libsdevent(void)
|
||||
{
|
||||
sd_event_exit(sd_loop, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
foreign_event_loop_cleanup_libsdevent(void)
|
||||
{
|
||||
sd_event_source_set_enabled(sd_timer, SD_EVENT_OFF);
|
||||
sd_timer = sd_event_source_unref(sd_timer);
|
||||
|
||||
sd_event_source_set_enabled(sd_signal, SD_EVENT_OFF);
|
||||
sd_signal = sd_event_source_unref(sd_signal);
|
||||
|
||||
sd_loop = sd_event_unref(sd_loop);
|
||||
}
|
||||
|
||||
const struct ops ops_sdevent = {
|
||||
foreign_event_loop_init_and_run_libsdevent,
|
||||
foreign_event_loop_stop_libsdevent,
|
||||
foreign_event_loop_cleanup_libsdevent
|
||||
};
|
||||
|
|
@ -196,10 +196,17 @@ int main(int argc, const char **argv)
|
|||
ops = &ops_glib;
|
||||
lwsl_notice("%s: using glib loop\n", __func__);
|
||||
} else
|
||||
#endif
|
||||
#if defined(LWS_WITH_SDEVENT)
|
||||
if (lws_cmdline_option(argc, argv, "--sd")) {
|
||||
info.options |= LWS_SERVER_OPTION_SDEVENT;
|
||||
ops = &ops_sdevent;
|
||||
lwsl_notice("%s: using sd-event loop\n", __func__);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
lwsl_err("This app only makes sense when used\n");
|
||||
lwsl_err(" with a foreign loop, --uv, --event, --glib, or --ev\n");
|
||||
lwsl_err(" with a foreign loop, --uv, --event, --glib, --ev or --sd\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -12,4 +12,4 @@ extern int lifetime, reported;
|
|||
void foreign_timer_service(void *foreign_loop);
|
||||
void signal_cb(int signum);
|
||||
|
||||
extern const struct ops ops_libuv, ops_libevent, ops_glib, ops_libev;
|
||||
extern const struct ops ops_libuv, ops_libevent, ops_glib, ops_libev, ops_sdevent;
|
||||
|
|
Loading…
Add table
Reference in a new issue