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

event libs: default to building as dynamically loaded plugins

Event lib support as it has been isn't scaling well, at the low level
libevent and libev headers have a namespace conflict so they can't
both be built into the same image, and at the distro level, binding
all the event libs to libwebsockets.so makes a bloaty situation for
packaging, lws will drag in all the event libs every time.

This patch implements the plan discussed here

https://github.com/warmcat/libwebsockets/issues/1980

and refactors the event lib support so they are built into isolated
plugins and bound at runtime according to what the application says
it wants to use.  The event lib plugins can be packaged individually
so that only the needed sets of support are installed (perhaps none
of them if the user code is OK with the default poll() loop).  And
dependent user code can mark the specific event loop plugin package
as required so pieces are added as needed.

The eventlib-foreign example is also refactored to build the selected
lib support isolated.

A readme is added detailing the changes and how to use them.

https://libwebsockets.org/git/libwebsockets/tree/READMEs/README.event-libs.md
This commit is contained in:
Andy Green 2020-08-27 15:37:14 +01:00
parent d98101d1e3
commit c6c7ab2b44
57 changed files with 1480 additions and 839 deletions

View file

@ -12,7 +12,7 @@
"build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}"
},
"linux-fedora-32/x86_64-amd/gcc": {
"build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}"
"build": "rm -rf build destdir ; mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}"
},
"linux-gentoo/x86_64-amd/gcc": {
"build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G ZIP\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}"

View file

@ -86,8 +86,8 @@ if(LWS_WITH_DISTRO_RECOMMENDED)
set(LWS_WITH_GLIB 1) # glib
set(LWS_WITH_LIBUV 1) # libuv
set(LWS_WITH_LIBEV 1) # libev
# libev + libevent cannot coexist at build-time
set(LWS_WITH_LIBEVENT 0)
set(LWS_WITH_LIBEVENT 1) # libevent
set(LWS_WITH_EVLIB_PLUGINS 1) # event libraries created as plugins / individual packages
set(LWS_WITHOUT_EXTENSIONS 0) # libz
set(LWS_ROLE_DBUS 1) # dbus-related libs
set(LWS_WITH_FTS 1) # selfcontained
@ -112,6 +112,17 @@ if(LWS_WITH_DISTRO_RECOMMENDED)
set(LWS_WITH_DIR 1) # selfcontained
endif()
# LWS_WITH_EVENT_LIBS is set if any event lib selected
if (LWS_WITH_LIBEV OR
LWS_WITH_LIBUV OR
LWS_WITH_LIBEVENT OR
LWS_WITH_GLIB)
set(LWS_WITH_EVENT_LIBS 1)
else()
unset(LWS_WITH_EVENT_LIBS)
endif()
if (LWS_WITH_SECURE_STREAMS_PROXY_API)
set(LWS_WITH_LWS_DSH 1)
set(LWS_WITH_UNIX_SOCK 1)
@ -184,10 +195,14 @@ if (NOT LWS_ROLE_WS)
set(LWS_WITHOUT_EXTENSIONS 1)
endif()
unset(LWS_WITH_LIBUV_INTERNAL)
if (LWS_WITH_LWSWS)
message(STATUS "LWS_WITH_LWSWS --> Enabling LWS_WITH_PLUGINS and LWS_WITH_LIBUV")
set(LWS_WITH_PLUGINS 1)
set(LWS_WITH_LIBUV 1)
set(LWS_WITH_LIBUV_INTERNAL 1)
set(LWS_WITH_EVENT_LIBS 1) # implied by LIBUV_INTERNAL
set(LWS_WITH_ACCESS_LOG 1)
set(LWS_WITH_SERVER_STATUS 1)
set(LWS_WITH_LEJP 1)
@ -249,6 +264,9 @@ endif()
if (WIN32)
set(LWS_MAX_SMP 1)
if (LWS_WITH_PLUGINS)
set(LWS_WITH_LIBUV_INTERNAL 1)
endif()
endif()
if (LWS_WITHOUT_SERVER)
@ -355,7 +373,7 @@ endif()
# set(LWS_WITH_ABSTRACT 1)
#endif()
if (LWS_WITH_LIBEV AND LWS_WITH_LIBEVENT)
if (NOT LWS_WITH_EVLIB_PLUGINS AND (LWS_WITH_LIBEV AND LWS_WITH_LIBEVENT))
message(FATAL_ERROR "Sorry libev and libevent conflict with each others' namespace, you can only have one or the other")
endif()

View file

@ -153,6 +153,13 @@ 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)
if (UNIX)
# since v4.1, on unix platforms default is build any event libs as runtime plugins
option(LWS_WITH_EVLIB_PLUGINS "Compile event lib support into runtime-selected plugins" ON)
else()
# otherwise default to linking the event lib(s) to libwebsockets.so
option(LWS_WITH_EVLIB_PLUGINS "Compile event lib support into runtime-selected plugins" OFF)
endif()
#
# LWS Drivers
#
@ -353,15 +360,19 @@ set(VERSION "${CPACK_PACKAGE_VERSION}")
set(CPACK_RPM_PACKAGE_RELEASE_DIST ON)
set(CPACK_RPM_FILE_NAME "RPM-DEFAULT")
set(CPACK_RPM_DEBUGINFO_PACKAGE ON)
# below makes path length problems in CI
set(CPACK_RPM_DEBUGINFO_PACKAGE OFF)
# below makes some kind of chimera rpm with binaries and sources
set(CPACK_RPM_PACKAGE_SOURCES OFF)
set(CPACK_RPM_INSTALL_WITH_EXEC ON)
set(CPACK_RPM_COMPONENT_INSTALL ON)
set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT")
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_DEBUGINFO_PACKAGE ON)
set(CPACK_DEBIAN_PACKAGE_SOURCE ON)
set(CPACK_DEBIAN_COMPONENT_INSTALL ON)
set(LWS_LIBRARY_VERSION ${CPACK_PACKAGE_VERSION})
set(LWS_LIBRARY_VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR})
@ -916,9 +927,9 @@ endif()
export(PACKAGE libwebsockets)
install(DIRECTORY include/libwebsockets
DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev_headers)
DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev)
install(FILES ${PROJECT_BINARY_DIR}/include/libwebsockets.h ${PROJECT_BINARY_DIR}/include/lws_config.h
DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev_headers)
DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev)
# Generate the config file for the installation tree.
get_filename_component(LWS_ABSOLUTE_INSTALL_CMAKE_DIR ${LWS_INSTALL_CMAKE_DIR} ABSOLUTE)

View file

@ -0,0 +1,80 @@
# lws event library support
## v4.0 and below
Before v4.1, lws allowed selecting some event library support for inclusion
in the libwebsockets library
Option|Feature
---|---
`LWS_WITH_GLIB`|glib
`LWS_WITH_LIBEVENT`|libevent
`LWS_WITH_LIBUV`|libuv
`LWS_WITH_LIBEV`|libev
The user code can select by `info->options` flags at runtime which event loop
it wants to use.
The only restriction is that libev and libevent can't coexist, because their
header namespace conflicts.
## v4.1 and above
Lws continues to support the old way described above, but there's an additional
new cmake option that decides how they are built if any are selected,
`LWS_WITH_EVLIB_PLUGINS`.
The old behaviour is set by `LWS_WITH_EVLIB_PLUGINS=0`, for UNIX platforms, this
is set to 1 by default. This causes the enabled event lib support to each be built into
its own dynamically linked plugin, and lws will bring in the requested support alone
at runtime after seeing the `info->options` flags requested by the user code.
This has two main benefits, first the conflict around building libevent and libev
together is removed, they each build isolated in their own plugin; the libwebsockets
core library build doesn't import any of their headers (see below for exception).
And second, for distro packaging, the event lib support plugins can be separately
packaged, and apps take dependencies on the specific event lib plugin package, which
itself depends on the libwebsockets core library. This allows just the needed
dependencies for the packageset without forcing everything to bring everything in.
Separately, lws itself has some optional dependencies on libuv, if you build lwsws
or on Windows you want plugins at all. CMake will detect these situations and
select to link the lws library itself to libuv if so as well, independent of whatever
is happening with the event lib support.
## evlib plugin install
The produced plugins are named
event lib|plugin name
---|---
glib|`libwebsockets-evlib_glib.so`
event|`libwebsockets-evlib_event.so`
uv|`libwebsockets-evlib_uv.so`
ev|`libwebsockets-evlib_ev.so`
The evlib plugins are installed alongside libwebsockets.so/.a into the configured
library dir, it's often `/usr/local/lib/` by default on linux.
Lws looks for them at runtime using the build-time-configured path.
## Component packaging
The canonical package name is `libwebsockets`, the recommended way to split the
packaging is put the expected libs and pkgconfig in `libwebsockets` or `libwebsockets-core`,
the latter is followed by the provided cmake, and produce an additional package per build
event library plugin, named, eg `libwebsockets-evlib_glib`, which has a dependency on
`libwebsockets[-core]`.
Applications that use the default event loop can directly require `libwebsockets[-core]`,
and application packages that need specific event loop support can just require, eg,
`libwebsockets-evlib_glib`, which will bring that in and the core lws pieces in one step.
There is then no problem with multiple apps requiring different event libs, they will
bring in all the necessary pieces which will not conflict either as packages or at
runtime.
## `LWS_WITH_DISTRO_RECOMMENDED`
The cmake helper config `LWS_WITH_DISTRO_RECOMMENDED` is adapted to build all the
event libs with the event lib plugin support enabled.

View file

@ -7,6 +7,7 @@
#endif
#define LWS_INSTALL_DATADIR "${CMAKE_INSTALL_PREFIX}/share"
#define LWS_INSTALL_LIBDIR "${CMAKE_INSTALL_PREFIX}/${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}"
#define LWS_LIBRARY_VERSION_MAJOR ${LWS_LIBRARY_VERSION_MAJOR}
#define LWS_LIBRARY_VERSION_MINOR ${LWS_LIBRARY_VERSION_MINOR}
#define LWS_LIBRARY_VERSION_PATCH_ELABORATED ${LWS_LIBRARY_VERSION_PATCH_ELABORATED}
@ -189,4 +190,7 @@
#cmakedefine LWS_WITH_ZIP_FOPS
#cmakedefine USE_OLD_CYASSL
#cmakedefine USE_WOLFSSL
#cmakedefine LWS_WITH_EVENT_LIBS
#cmakedefine LWS_WITH_EVLIB_PLUGINS
#cmakedefine LWS_WITH_LIBUV_INTERNAL

View file

@ -190,21 +190,17 @@ typedef unsigned long long lws_intptr_t;
#endif
#endif
#if defined(LWS_WITH_LIBEV)
#include <ev.h>
#endif /* LWS_WITH_LIBEV */
#ifdef LWS_WITH_LIBUV
#if defined(LWS_WITH_LIBUV_INTERNAL)
#include <uv.h>
#ifdef LWS_HAVE_UV_VERSION_H
#include <uv-version.h>
#endif
#ifdef LWS_HAVE_NEW_UV_VERSION_H
#include <uv/version.h>
#endif
#endif /* LWS_WITH_LIBUV */
#if defined(LWS_WITH_LIBEVENT)
#include <event2/event.h>
#endif /* LWS_WITH_LIBEVENT */
#endif
#if defined(LWS_WITH_TLS)
@ -610,6 +606,7 @@ struct lws;
#endif
#include <libwebsockets/lws-eventlib-exports.h>
#include <libwebsockets/lws-i2c.h>
#include <libwebsockets/lws-spi.h>
#include <libwebsockets/lws-gpio.h>

View file

@ -0,0 +1,61 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
*
* 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:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* 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.
*
* These are exports needed by event lib plugins.
*
* You should consider these opaque for normal user code.
*/
LWS_VISIBLE LWS_EXTERN void *
lws_realloc(void *ptr, size_t size, const char *reason);
LWS_VISIBLE LWS_EXTERN void
lws_vhost_destroy1(struct lws_vhost *vh);
LWS_VISIBLE LWS_EXTERN void
lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason,
const char *caller);
struct lws_context_per_thread;
LWS_VISIBLE LWS_EXTERN void
lws_service_do_ripe_rxflow(struct lws_context_per_thread *pt);
#if !defined(wsi_from_fd) && !defined(WIN32) && !defined(_WIN32)
struct lws_context;
LWS_VISIBLE LWS_EXTERN struct lws *
wsi_from_fd(const struct lws_context *context, int fd);
#endif
LWS_VISIBLE LWS_EXTERN int
_lws_plat_service_forced_tsi(struct lws_context *context, int tsi);
LWS_VISIBLE LWS_EXTERN void
lws_context_destroy2(struct lws_context *context);
LWS_VISIBLE LWS_EXTERN void
lws_destroy_event_pipe(struct lws *wsi);
LWS_VISIBLE LWS_EXTERN void
__lws_close_free_wsi_final(struct lws *wsi);

View file

@ -194,8 +194,6 @@ lws_pvo_get_str(void *in, const char *name, const char **result);
LWS_VISIBLE LWS_EXTERN int
lws_protocol_init(struct lws_context *context);
#ifdef LWS_WITH_PLUGINS
#define LWS_PLUGIN_API_MAGIC 190
/*
@ -244,7 +242,7 @@ struct lws_plugin {
const lws_plugin_header_t *hdr;
union {
#if defined(LWS_WITH_LIBUV)
#if defined(LWS_WITH_LIBUV) && defined(UV_ERRNO_MAP)
#if (UV_VERSION_MAJOR > 0)
uv_lib_t lib; /**< shared library pointer */
#endif
@ -253,6 +251,16 @@ struct lws_plugin {
} u;
};
/*
* Event lib library plugin type (when LWS_WITH_EVLIB_PLUGINS)
* Public so new event libs can equally be supported outside lws itself
*/
typedef struct lws_plugin_evlib {
lws_plugin_header_t hdr;
const struct lws_event_loop_ops *ops;
} lws_plugin_evlib_t;
typedef int (*each_plugin_cb_t)(struct lws_plugin *p, void *user);
/**
@ -297,6 +305,5 @@ lws_plugins_init(struct lws_plugin **pplugin, const char * const *d,
LWS_VISIBLE LWS_EXTERN int
lws_plugins_destroy(struct lws_plugin **pplugin, each_plugin_cb_t each,
void *each_user);
#endif
///@}

View file

@ -167,7 +167,8 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd);
* APIs specific to libuv event loop itegration
*/
///@{
#ifdef LWS_WITH_LIBUV
#if defined(LWS_WITH_LIBUV) && defined(UV_ERRNO_MAP)
/*
* Any direct libuv allocations in lws protocol handlers must participate in the
* lws reference counting scheme. Two apis are provided:

View file

@ -122,7 +122,6 @@ configure_file(
add_subdir_include_dirs(core)
add_subdir_include_dirs(misc)
add_subdir_include_dirs(system)
add_subdir_include_dirs(event-libs)
if (LWS_WITH_DRIVERS)
add_subdir_include_dirs(drivers)
@ -144,6 +143,8 @@ if (LWS_WITH_SECURE_STREAMS)
add_subdir_include_dirs(secure-streams)
endif()
add_subdir_include_dirs(event-libs)
if (LWS_WITH_STATIC)
if (LWS_STATIC_PIC)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
@ -249,12 +250,12 @@ endif()
# Install libs and headers.
install(TARGETS ${LWS_LIBRARIES}
EXPORT LibwebsocketsTargets
LIBRARY DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT libraries
ARCHIVE DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT libraries
RUNTIME DESTINATION "${LWS_INSTALL_BIN_DIR}" COMPONENT libraries # Windows DLLs
LIBRARY DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT core
ARCHIVE DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT core
RUNTIME DESTINATION "${LWS_INSTALL_BIN_DIR}" COMPONENT core # Windows DLLs
PUBLIC_HEADER DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev)
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries" PARENT_SCOPE)
#set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries" PARENT_SCOPE)
set(CPACK_COMPONENT_DEV_DISPLAY_NAME "Development files" PARENT_SCOPE)

View file

@ -49,6 +49,7 @@ lws_create_new_server_wsi(struct lws_vhost *vhost, int fixed_tsi)
{
struct lws *new_wsi;
int n = fixed_tsi;
size_t s = sizeof(struct lws);
if (n < 0)
n = lws_get_idlest_tsi(vhost->context);
@ -58,12 +59,20 @@ lws_create_new_server_wsi(struct lws_vhost *vhost, int fixed_tsi)
return NULL;
}
new_wsi = lws_zalloc(sizeof(struct lws), "new server wsi");
#if defined(LWS_WITH_EVENT_LIBS)
s += vhost->context->event_loop_ops->evlib_size_wsi;
#endif
new_wsi = lws_zalloc(s, "new server wsi");
if (new_wsi == NULL) {
lwsl_err("Out of memory for new connection\n");
return NULL;
}
#if defined(LWS_WITH_EVENT_LIBS)
new_wsi->evlib_wsi = (uint8_t *)new_wsi + sizeof(*new_wsi);
#endif
new_wsi->wsistate |= LWSIFR_SERVER;
new_wsi->tsi = n;
lwsl_debug("new wsi %p joining vhost %s, tsi %d\n", new_wsi,

View file

@ -31,6 +31,7 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
const char *local = i->protocol;
struct lws *wsi, *safe = NULL;
const struct lws_protocols *p;
size_t s = sizeof(struct lws);
const char *cisin[CIS_COUNT];
int tid = 0, n, m;
size_t size;
@ -54,10 +55,18 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
/* PHASE 1: create a bare wsi */
wsi = lws_zalloc(sizeof(struct lws), "client wsi");
#if defined(LWS_WITH_EVENT_LIBS)
s += i->context->event_loop_ops->evlib_size_wsi;
#endif
wsi = lws_zalloc(s, "client wsi");
if (wsi == NULL)
goto bail;
#if defined(LWS_WITH_EVENT_LIBS)
wsi->evlib_wsi = (uint8_t *)wsi + sizeof(*wsi);
#endif
/*
* Until we exit, we can report connection failure directly to the
* caller without needing to call through to protocol CONNECTION_ERROR.

View file

@ -27,8 +27,7 @@
int
_lws_change_pollfd(struct lws *wsi, int _and, int _or, struct lws_pollargs *pa)
{
#if !defined(LWS_WITH_LIBUV) && !defined(LWS_WITH_LIBEV) && \
!defined(LWS_WITH_LIBEVENT) && !defined(LWS_WITH_GLIB)
#if !defined(LWS_WITH_EVENT_LIBS)
volatile struct lws_context_per_thread *vpt;
#endif
struct lws_context_per_thread *pt;
@ -72,8 +71,7 @@ _lws_change_pollfd(struct lws *wsi, int _and, int _or, struct lws_pollargs *pa)
assert(wsi->position_in_fds_table < (int)pt->fds_count);
#if !defined(LWS_WITH_LIBUV) && !defined(LWS_WITH_LIBEV) && \
!defined(LWS_WITH_LIBEVENT) && !defined(LWS_WITH_GLIB)
#if !defined(LWS_WITH_EVENT_LIBS)
/*
* This only applies when we use the default poll() event loop.
*

View file

@ -428,22 +428,8 @@ struct lws_context_per_thread {
#endif
/* --- event library based members --- */
#if defined(LWS_WITH_LIBEV)
struct lws_pt_eventlibs_libev ev;
#endif
#if defined(LWS_WITH_LIBUV)
struct lws_pt_eventlibs_libuv uv;
#endif
#if defined(LWS_WITH_LIBEVENT)
struct lws_pt_eventlibs_libevent event;
#endif
#if defined(LWS_WITH_GLIB)
struct lws_pt_eventlibs_glib glib;
#endif
#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBUV) || \
defined(LWS_WITH_LIBEVENT) || defined(LWS_WITH_GLIB)
struct lws_signal_watcher w_sigint;
#if defined(LWS_WITH_EVENT_LIBS)
void *evlib_pt; /* overallocated */
#endif
#if defined(LWS_WITH_DETAILED_LATENCY)
@ -530,8 +516,8 @@ struct lws_vhost {
char socks_user[96];
char socks_password[96];
#endif
#if defined(LWS_WITH_LIBEV)
struct lws_io_watcher w_accept;
#if defined(LWS_WITH_EVENT_LIBS)
void *evlib_vh; /* overallocated */
#endif
#if defined(LWS_WITH_SERVER_STATUS)
struct lws_conn_stats conn_stats;
@ -719,12 +705,8 @@ struct lws {
/* lifetime members */
#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBUV) || \
defined(LWS_WITH_LIBEVENT) || defined(LWS_WITH_GLIB)
struct lws_io_watcher w_read;
#endif
#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBEVENT)
struct lws_io_watcher w_write;
#if defined(LWS_WITH_EVENT_LIBS)
void *evlib_wsi; /* overallocated */
#endif
#if defined(LWS_WITH_DETAILED_LATENCY)
@ -1158,6 +1140,7 @@ lws_libuv_closehandle(struct lws *wsi);
int
lws_libuv_check_watcher_active(struct lws *wsi);
#if defined(LWS_WITH_EVLIB_PLUGINS) || defined(LWS_WITH_PLUGINS)
const lws_plugin_header_t *
lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath,
const char *sofilename, const char *_class,
@ -1165,6 +1148,7 @@ lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath,
int
lws_plat_destroy_dl(struct lws_plugin *p);
#endif
struct lws *
lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd);

View file

@ -175,9 +175,9 @@ lws_json_dump_context(const struct lws_context *context, char *buf, int len,
struct lws_cgi * const *pcgi;
#endif
#ifdef LWS_WITH_LIBUV
uv_uptime(&d);
#endif
//#ifdef LWS_WITH_LIBUV &&
// uv_uptime(&d);
//#endif
buf += lws_snprintf(buf, end - buf, "{ "
"\"version\":\"%s\",\n"

View file

@ -714,6 +714,8 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd,
case LWS_HPI_RET_HANDLED:
break;
case LWS_HPI_RET_PLEASE_CLOSE_ME:
lwsl_notice("%s: %s pollin says please close me\n", __func__,
wsi->role_ops->name);
close_and_handled:
lwsl_debug("%p: Close and handled\n", wsi);
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
@ -724,7 +726,7 @@ close_and_handled:
* it waits for libuv service to complete the first async
* close
*/
if (context->event_loop_ops == &event_loop_ops_uv)
if (!strcmp(context->event_loop_ops->name, "libuv"))
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
"close_and_handled uv repeat test");
#endif

View file

@ -46,22 +46,6 @@ const struct lws_role_ops *available_roles[] = {
NULL
};
const struct lws_event_loop_ops *available_event_libs[] = {
#if defined(LWS_WITH_POLL)
&event_loop_ops_poll,
#endif
#if defined(LWS_WITH_LIBUV)
&event_loop_ops_uv,
#endif
#if defined(LWS_WITH_LIBEVENT)
&event_loop_ops_event,
#endif
#if defined(LWS_WITH_LIBEV)
&event_loop_ops_ev,
#endif
NULL
};
#if defined(LWS_WITH_ABSTRACT)
const struct lws_protocols *available_abstract_protocols[] = {
#if defined(LWS_ROLE_RAW)
@ -471,8 +455,7 @@ struct lws_vhost *
lws_create_vhost(struct lws_context *context,
const struct lws_context_creation_info *info)
{
struct lws_vhost *vh = lws_zalloc(sizeof(*vh), "create vhost"),
**vh1 = &context->vhost_list;
struct lws_vhost *vh, **vh1 = &context->vhost_list;
const struct lws_http_mount *mounts;
const struct lws_protocols *pcols = info->protocols;
#ifdef LWS_WITH_PLUGINS
@ -490,9 +473,19 @@ lws_create_vhost(struct lws_context *context,
#endif
int n;
vh = lws_zalloc(sizeof(*vh)
#if defined(LWS_WITH_EVENT_LIBS)
+ context->event_loop_ops->evlib_size_vh
#endif
, __func__);
if (!vh)
return NULL;
#if defined(LWS_WITH_EVENT_LIBS)
vh->evlib_vh = (void *)&vh[1];
#endif
#if LWS_MAX_SMP > 1
pthread_mutex_init(&vh->lock, NULL);
#endif
@ -915,6 +908,7 @@ lws_cancel_service(struct lws_context *context)
int
lws_create_event_pipes(struct lws_context *context)
{
size_t s = sizeof(struct lws);
struct lws *wsi;
int n;
@ -932,11 +926,18 @@ lws_create_event_pipes(struct lws_context *context)
if (context->pt[n].pipe_wsi)
return 0;
wsi = lws_zalloc(sizeof(*wsi), "event pipe wsi");
#if defined(LWS_WITH_EVENT_LIBS)
s += context->event_loop_ops->evlib_size_wsi;
#endif
wsi = lws_zalloc(s, "event pipe wsi");
if (!wsi) {
lwsl_err("%s: Out of mem\n", __func__);
return 1;
}
#if defined(LWS_WITH_EVENT_LIBS)
wsi->evlib_wsi = (uint8_t *)wsi + sizeof(*wsi);
#endif
wsi->a.context = context;
lws_role_transition(wsi, 0, LRS_UNCONNECTED, &role_ops_pipe);
wsi->a.protocol = NULL;

View file

@ -850,8 +850,7 @@ _lws_generic_transaction_completed_active_conn(struct lws **_wsi, char take_vh_l
* new guy and snuff out the old guy's magic spark at that level as well
*/
#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBUV) || \
defined(LWS_WITH_LIBEVENT) || defined(LWS_WITH_GLIB)
#if defined(LWS_WITH_EVENT_LIBS)
if (wsi->a.context->event_loop_ops->destroy_wsi)
wsi->a.context->event_loop_ops->destroy_wsi(wsi);
if (wsi->a.context->event_loop_ops->sock_accept)

View file

@ -331,6 +331,22 @@ static const char * const opts_str =
#endif
#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS)
static const struct lws_evlib_map {
uint64_t flag;
const char *name;
} map[] = {
{ LWS_SERVER_OPTION_LIBUV, "evlib_uv" },
{ LWS_SERVER_OPTION_LIBEVENT, "evlib_event" },
{ LWS_SERVER_OPTION_GLIB, "evlib_glib" },
{ LWS_SERVER_OPTION_LIBEV, "evlib_ev" },
};
static const char * const dlist[] = {
LWS_INSTALL_LIBDIR,
NULL
};
#endif
struct lws_context *
lws_create_context(const struct lws_context_creation_info *info)
{
@ -360,6 +376,10 @@ lws_create_context(const struct lws_context_creation_info *info)
#endif
size = sizeof(struct lws_context);
int n, lpf = info->fd_limit_per_thread;
const lws_plugin_evlib_t *plev = NULL;
#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS)
struct lws_plugin *evlib_plugin_list = NULL;
#endif
if (lpf) {
lpf+= 2;
@ -407,6 +427,102 @@ lws_create_context(const struct lws_context_creation_info *info)
#if !defined(LWS_PLAT_FREERTOS)
size += (count_threads * sizeof(struct lws));
#endif
#endif /* network */
#if defined(LWS_WITH_POLL)
{
extern const lws_plugin_evlib_t evlib_poll;
plev = &evlib_poll;
}
#endif
#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS)
/*
* New style dynamically loaded event lib support
*
* We have to pick and load the event lib plugin before we allocate
* the context object, so we can overallocate it correctly
*/
lwsl_info("%s: ev lib path %s\n", __func__, LWS_INSTALL_LIBDIR);
for (n = 0; n < (int)LWS_ARRAY_SIZE(map); n++) {
if (!lws_check_opt(info->options, map[n].flag))
continue;
if (lws_plugins_init(&evlib_plugin_list,
dlist, "lws_evlib_plugin",
map[n].name, NULL, NULL)) {
lwsl_err("%s: failed to load %s\n", __func__,
map[n].name);
goto bail;
}
if (!evlib_plugin_list) {
lwsl_err("%s: unable to load evlib plugin %s\n",
__func__, map[n].name);
goto bail;
}
plev = (const lws_plugin_evlib_t *)evlib_plugin_list->hdr;
break;
}
#else
#if defined(LWS_WITH_EVENT_LIBS)
/*
* set the context event loops ops struct
*
* after this, all event_loop actions use the generic ops
*/
/*
* oldstyle built-in event lib support
*
* We have composed them into the libwebsockets lib itself, we can
* just pick the ops we want and done
*/
#if defined(LWS_WITH_LIBUV)
if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBUV)) {
extern const lws_plugin_evlib_t evlib_uv;
plev = &evlib_uv;
}
#endif
#if defined(LWS_WITH_LIBEVENT)
if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBEVENT)) {
extern const lws_plugin_evlib_t evlib_event;
plev = &evlib_event;
}
#endif
#if defined(LWS_WITH_GLIB)
if (lws_check_opt(info->options, LWS_SERVER_OPTION_GLIB)) {
extern const lws_plugin_evlib_t evlib_glib;
plev = &evlib_glib;
}
#endif
#if defined(LWS_WITH_LIBEV)
if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBEV)) {
extern const lws_plugin_evlib_t evlib_ev;
plev = &evlib_ev;
}
#endif
#endif /* with event libs */
#endif /* not with ev plugins */
if (!plev)
goto fail_event_libs;
#if defined(LWS_WITH_NETWORK)
size += plev->ops->evlib_size_ctx /* the ctx evlib priv */ +
(count_threads * plev->ops->evlib_size_pt) /* the pt evlib priv */;
lwsl_info("Event loop: %s\n", plev->ops->name);
#endif
context = lws_zalloc(size, "context");
@ -415,6 +531,18 @@ lws_create_context(const struct lws_context_creation_info *info)
return NULL;
}
#if defined(LWS_WITH_NETWORK)
context->event_loop_ops = plev->ops;
#endif
#if defined(LWS_WITH_EVENT_LIBS)
/* at the very end */
context->evlib_ctx = (uint8_t *)context + size -
plev->ops->evlib_size_ctx;
#endif
#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS)
context->evlib_plugin_list = evlib_plugin_list;
#endif
#if !defined(LWS_PLAT_FREERTOS)
context->uid = info->uid;
context->gid = info->gid;
@ -460,7 +588,7 @@ lws_create_context(const struct lws_context_creation_info *info)
if (info->extensions)
lwsl_warn("%s: LWS_WITHOUT_EXTENSIONS but extensions ptr set\n", __func__);
#endif
#endif
#endif /* network */
#if defined(LWS_WITH_SECURE_STREAMS)
#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
@ -603,52 +731,9 @@ lws_create_context(const struct lws_context_creation_info *info)
}
#if defined(LWS_WITH_NETWORK)
context->token_limits = info->token_limits;
/*
* set the context event loops ops struct
*
* after this, all event_loop actions use the generic ops
*/
#if defined(LWS_WITH_POLL)
context->event_loop_ops = &event_loop_ops_poll;
#endif
if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV))
#if defined(LWS_WITH_LIBUV)
context->event_loop_ops = &event_loop_ops_uv;
#else
goto fail_event_libs;
#endif
if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBEV))
#if defined(LWS_WITH_LIBEV)
context->event_loop_ops = &event_loop_ops_ev;
#else
goto fail_event_libs;
#endif
if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBEVENT))
#if defined(LWS_WITH_LIBEVENT)
context->event_loop_ops = &event_loop_ops_event;
#else
goto fail_event_libs;
#endif
if (lws_check_opt(context->options, LWS_SERVER_OPTION_GLIB))
#if defined(LWS_WITH_GLIB)
context->event_loop_ops = &event_loop_ops_glib;
#else
goto fail_event_libs;
#endif
if (!context->event_loop_ops)
goto fail_event_libs;
lwsl_info("Using event loop: %s\n", context->event_loop_ops->name);
#endif
#if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK)
time(&context->tls.last_cert_check_s);
@ -728,7 +813,7 @@ lws_create_context(const struct lws_context_creation_info *info)
}
#endif
n = 0;
n = 0;
#if defined(LWS_WITH_NETWORK)
context->default_retry.retry_ms_table = default_backoff_table;
@ -773,6 +858,11 @@ n = 0;
memset(context->pt[n].fake_wsi, 0, sizeof(struct lws));
#endif
#if defined(LWS_WITH_EVENT_LIBS)
context->pt[n].evlib_pt = u;
u += plev->ops->evlib_size_pt;
#endif
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
context->pt[n].http.ah_list = NULL;
context->pt[n].http.ah_pool_length = 0;
@ -1100,19 +1190,9 @@ bail:
return NULL;
#if defined(LWS_WITH_NETWORK)
fail_event_libs:
lwsl_err("Requested event library support not configured, available:\n");
{
extern const struct lws_event_loop_ops *available_event_libs[];
const struct lws_event_loop_ops **elops = available_event_libs;
lwsl_err("Requested event library support not configured\n");
while (*elops) {
lwsl_err(" - %s\n", (*elops)->name);
elops++;
}
}
#endif
lws_free(context);
return NULL;
@ -1282,6 +1362,11 @@ lws_context_destroy3(struct lws_context *context)
lws_free(df);
};
#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS)
if (context->evlib_plugin_list)
lws_plugins_destroy(&context->evlib_plugin_list, NULL, NULL);
#endif
lws_free(context);
lwsl_debug("%s: ctx %p freed\n", __func__, context);

View file

@ -212,56 +212,24 @@ struct lws_ring {
struct lws_protocols;
struct lws;
#if defined(LWS_WITH_NETWORK)
#if defined(LWS_WITH_NETWORK) /* network */
#include "private-lib-event-libs.h"
#if defined(LWS_WITH_SECURE_STREAMS)
#include "private-lib-secure-streams.h"
#endif
#if defined(LWS_WITH_SYS_SMD)
#include "private-lib-system-smd.h"
#endif
struct lws_io_watcher {
#ifdef LWS_WITH_LIBEV
struct lws_io_watcher_libev ev;
#endif
#ifdef LWS_WITH_LIBUV
struct lws_io_watcher_libuv uv;
#endif
#ifdef LWS_WITH_LIBEVENT
struct lws_io_watcher_libevent event;
#endif
#ifdef LWS_WITH_GLIB
struct lws_io_watcher_glib glib;
#endif
struct lws_context *context;
uint8_t actual_events;
};
struct lws_signal_watcher {
#ifdef LWS_WITH_LIBEV
struct lws_signal_watcher_libev ev;
#endif
#ifdef LWS_WITH_LIBUV
struct lws_signal_watcher_libuv uv;
#endif
#ifdef LWS_WITH_LIBEVENT
struct lws_signal_watcher_libevent event;
#endif
struct lws_context *context;
};
struct lws_foreign_thread_pollfd {
struct lws_foreign_thread_pollfd *next;
int fd_index;
int _and;
int _or;
};
#endif
#endif /* network */
#if LWS_MAX_SMP > 1
@ -368,20 +336,13 @@ struct lws_context {
* LWS_WITH_NETWORK =====>
*/
#if defined(LWS_WITH_LIBEV)
struct lws_context_eventlibs_libev ev;
#endif
#if defined(LWS_WITH_LIBUV)
struct lws_context_eventlibs_libuv uv;
#endif
#if defined(LWS_WITH_LIBEVENT)
struct lws_context_eventlibs_libevent event;
#endif
#if defined(LWS_WITH_GLIB)
struct lws_context_eventlibs_glib glib;
#if defined(LWS_WITH_EVENT_LIBS)
struct lws_plugin *evlib_plugin_list;
void *evlib_ctx; /* overallocated */
#endif
#if defined(LWS_WITH_TLS)
struct lws_context_tls tls;
struct lws_context_tls tls;
#endif
#if defined(LWS_WITH_DRIVERS)
lws_netdevs_t netdevs;
@ -427,7 +388,7 @@ struct lws_context {
const char *server_string;
#endif
struct lws_event_loop_ops *event_loop_ops;
const struct lws_event_loop_ops *event_loop_ops;
#endif
#if defined(LWS_WITH_TLS)

View file

@ -24,15 +24,50 @@
include_directories(.)
macro(create_evlib_plugin PLUGIN_NAME MAIN_SRC PLUGIN_HDR EVLIB)
set(PLUGIN_SRCS ${MAIN_SRC})
source_group("Headers Private" FILES ${PLUGIN_HDR})
source_group("Sources" FILES ${MAIN_SRC})
add_library(websockets-${PLUGIN_NAME} SHARED ${MAIN_SRC} ${PLUGIN_HDR})
foreach(libpath ${LWS_DEP_LIB_PATHS})
target_link_directories(${TEST_NAME} ${libpath})
endforeach()
target_link_libraries(websockets-${PLUGIN_NAME} websockets_shared ${EVLIB})
add_dependencies(websockets-${PLUGIN_NAME} websockets_shared)
target_include_directories(websockets-${PLUGIN_NAME} PRIVATE
${PLUGIN_INCLUDE} ${LWS_LIB_BUILD_INC_PATHS})
# Set test app specific defines.
# set_property(TARGET ${PLUGIN_NAME}
# PROPERTY COMPILE_DEFINITIONS
# INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/evlib-plugins"
#)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
install(TARGETS websockets-${PLUGIN_NAME}
EXPORT LibwebsocketsTargets
LIBRARY DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}"
COMPONENT ${PLUGIN_NAME})
list(APPEND EVLIB_PLUGINS_LIST websockets-${PLUGIN_NAME})
endmacro()
#
# These can coexist, except libev conflicts with libevent
# poll support gets built into the lib as the default
#
if (LWS_WITH_POLL)
add_subdir_include_directories(poll)
endif()
if (LWS_WITH_LIBUV)
if (LWS_WITH_LIBUV OR LWS_WITH_LIBUV_INTERNAL)
add_subdir_include_directories(libuv)
set(LWS_HAVE_UV_VERSION_H ${LWS_HAVE_UV_VERSION_H} PARENT_SCOPE)
set(LWS_HAVE_NEW_UV_VERSION_H ${LWS_HAVE_NEW_UV_VERSION_H} PARENT_SCOPE)
@ -52,8 +87,12 @@ if (LWS_WITH_LIBEV)
set(LWS_HAVE_EVBACKEND_IOURING ${LWS_HAVE_EVBACKEND_IOURING} PARENT_SCOPE)
endif()
#
# Keep explicit parent scope exports at end
#
export_to_parent_intermediate()
set(EVLIB_PLUGINS_LIST ${EVLIB_PLUGINS_LIST} PARENT_SCOPE)

View file

@ -52,13 +52,24 @@ endif()
message("glib include dir: ${GLIB_INCLUDE_DIRS}")
message("glib libraries: ${GLIB_LIBRARIES}")
include_directories("${GLIB_INCLUDE_DIRS}")
list(APPEND LIB_LIST ${GLIB_LIBRARIES})
if (LWS_WITH_NETWORK)
list(APPEND SOURCES
event-libs/glib/glib.c)
if (LWS_WITH_EVLIB_PLUGINS)
create_evlib_plugin(evlib_glib
glib.c
private-lib-event-libs-glib.h
${GLIB_LIBRARIES})
else()
list(APPEND LIB_LIST ${GLIB_LIBRARIES})
if (LWS_WITH_NETWORK)
list(APPEND SOURCES
event-libs/glib/glib.c)
endif()
endif()
#
# Keep explicit parent scope exports at end
#

View file

@ -26,13 +26,18 @@
#include <glib-unix.h>
#include "private-lib-event-libs-glib.h"
#if !defined(G_SOURCE_FUNC)
#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f))
#endif
#define wsi_to_subclass(_w) ((_w)->w_read.glib.source)
#define pt_to_priv_glib(_pt) ((struct lws_pt_eventlibs_glib *)(_pt)->evlib_pt)
#define wsi_to_priv_glib(_w) ((struct lws_wsi_eventlibs_glib *)(_w)->evlib_wsi)
#define wsi_to_subclass(_w) (wsi_to_priv_glib(_w)->w_read.source)
#define wsi_to_gsource(_w) ((GSource *)wsi_to_subclass(_w))
#define pt_to_loop(_pt) ((_pt)->glib.loop)
#define pt_to_loop(_pt) (pt_to_priv_glib(_pt)->loop)
#define pt_to_g_main_context(_pt) g_main_loop_get_context(pt_to_loop(_pt))
#define lws_gs_valid(t) (t.gs)
@ -68,17 +73,17 @@ lws_glib_check(GSource *src)
static int
lws_glib_set_idle(struct lws_context_per_thread *pt)
{
if (lws_gs_valid(pt->glib.idle))
if (lws_gs_valid(pt_to_priv_glib(pt)->idle))
return 0;
pt->glib.idle.gs = g_idle_source_new();
if (!pt->glib.idle.gs)
pt_to_priv_glib(pt)->idle.gs = g_idle_source_new();
if (!pt_to_priv_glib(pt)->idle.gs)
return 1;
g_source_set_callback(pt->glib.idle.gs, lws_glib_idle_timer_cb, pt,
NULL);
pt->glib.idle.tag = g_source_attach(pt->glib.idle.gs,
pt_to_g_main_context(pt));
g_source_set_callback(pt_to_priv_glib(pt)->idle.gs,
lws_glib_idle_timer_cb, pt, NULL);
pt_to_priv_glib(pt)->idle.tag = g_source_attach(
pt_to_priv_glib(pt)->idle.gs, pt_to_g_main_context(pt));
return 0;
}
@ -86,16 +91,17 @@ lws_glib_set_idle(struct lws_context_per_thread *pt)
static int
lws_glib_set_timeout(struct lws_context_per_thread *pt, unsigned int ms)
{
lws_gs_destroy(pt->glib.hrtimer);
lws_gs_destroy(pt_to_priv_glib(pt)->hrtimer);
pt->glib.hrtimer.gs = g_timeout_source_new(ms);
if (!pt->glib.hrtimer.gs)
pt_to_priv_glib(pt)->hrtimer.gs = g_timeout_source_new(ms);
if (!pt_to_priv_glib(pt)->hrtimer.gs)
return 1;
g_source_set_callback(pt->glib.hrtimer.gs, lws_glib_hrtimer_cb, pt,
NULL);
pt->glib.hrtimer.tag = g_source_attach(pt->glib.hrtimer.gs,
pt_to_g_main_context(pt));
g_source_set_callback(pt_to_priv_glib(pt)->hrtimer.gs,
lws_glib_hrtimer_cb, pt, NULL);
pt_to_priv_glib(pt)->hrtimer.tag = g_source_attach(
pt_to_priv_glib(pt)->hrtimer.gs,
pt_to_g_main_context(pt));
return 0;
}
@ -135,7 +141,7 @@ lws_glib_dispatch(GSource *src, GSourceFunc x, gpointer userData)
lws_service_fd_tsi(sub->wsi->a.context, &eventfd, sub->wsi->tsi);
if (!lws_gs_valid(pt->glib.idle))
if (!lws_gs_valid(pt_to_priv_glib(pt)->idle))
lws_glib_set_idle(pt);
if (pt->destroy_self)
@ -166,7 +172,7 @@ lws_glib_hrtimer_cb(void *p)
lws_pt_lock(pt, __func__);
lws_gs_destroy(pt->glib.hrtimer);
lws_gs_destroy(pt_to_priv_glib(pt)->hrtimer);
us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
lws_now_usecs());
@ -217,7 +223,7 @@ lws_glib_idle_timer_cb(void *p)
* We reenable the idle callback on the next network or scheduled event
*/
lws_gs_destroy(pt->glib.idle);
lws_gs_destroy(pt_to_priv_glib(pt)->idle);
return FALSE;
}
@ -242,12 +248,12 @@ static int
elops_init_context_glib(struct lws_context *context,
const struct lws_context_creation_info *info)
{
int n;
// int n;
context->eventlib_signal_cb = info->signal_cb;
for (n = 0; n < context->count_threads; n++)
context->pt[n].w_sigint.context = context;
// for (n = 0; n < context->count_threads; n++)
// pt_to_priv_glib(&context->pt[n])->w_sigint.context = context;
return 0;
}
@ -256,6 +262,7 @@ static int
elops_accept_glib(struct lws *wsi)
{
struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
struct lws_wsi_eventlibs_glib *wsipr = wsi_to_priv_glib(wsi);
int fd;
assert(!wsi_to_subclass(wsi));
@ -266,7 +273,7 @@ elops_accept_glib(struct lws *wsi)
if (!wsi_to_subclass(wsi))
return 1;
wsi->w_read.context = wsi->a.context;
wsipr->w_read.context = wsi->a.context;
wsi_to_subclass(wsi)->wsi = wsi;
if (wsi->role_ops->file_handle)
@ -276,7 +283,7 @@ elops_accept_glib(struct lws *wsi)
wsi_to_subclass(wsi)->tag = g_source_add_unix_fd(wsi_to_gsource(wsi),
fd, (GIOCondition)LWS_POLLIN);
wsi->w_read.actual_events = LWS_POLLIN;
wsipr->w_read.actual_events = LWS_POLLIN;
g_source_set_callback(wsi_to_gsource(wsi),
G_SOURCE_FUNC(lws_service_fd), wsi->a.context, NULL);
@ -290,6 +297,7 @@ 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;
@ -304,7 +312,7 @@ elops_init_pt_glib(struct lws_context *context, void *_loop, int tsi)
return -1;
}
pt->glib.loop = loop;
ptpr->loop = loop;
/*
* Initialize all events with the listening sockets
@ -325,7 +333,7 @@ elops_init_pt_glib(struct lws_context *context, void *_loop, int tsi)
if (pt->event_loop_foreign)
return 0;
pt->glib.sigint.tag = g_unix_signal_add(SIGINT,
ptpr->sigint.tag = g_unix_signal_add(SIGINT,
G_SOURCE_FUNC(lws_glib_sigint_cb), pt);
return 0;
@ -339,9 +347,11 @@ static void
elops_io_glib(struct lws *wsi, int flags)
{
struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
GIOCondition cond = wsi->w_read.actual_events | G_IO_ERR;
struct lws_wsi_eventlibs_glib *wsipr = wsi_to_priv_glib(wsi);
GIOCondition cond = wsipr->w_read.actual_events | G_IO_ERR;
if (!pt_to_loop(pt) || wsi->a.context->being_destroyed || pt->is_destroyed)
if (!pt_to_loop(pt) || wsi->a.context->being_destroyed ||
pt->is_destroyed)
return;
if (!wsi_to_subclass(wsi))
@ -366,7 +376,7 @@ elops_io_glib(struct lws *wsi, int flags)
cond |= G_IO_OUT;
}
wsi->w_read.actual_events = cond;
wsipr->w_read.actual_events = cond;
lwsl_debug("%s: wsi %p, fd %d, 0x%x/0x%x\n", __func__, wsi,
wsi->desc.sockfd, flags, (int)cond);
@ -414,6 +424,7 @@ 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))
@ -429,12 +440,12 @@ elops_destroy_pt_glib(struct lws_context *context, int tsi)
vh = vh->vhost_next;
}
lws_gs_destroy(pt->glib.idle);
lws_gs_destroy(pt->glib.hrtimer);
lws_gs_destroy(ptpr->idle);
lws_gs_destroy(ptpr->hrtimer);
if (!pt->event_loop_foreign) {
g_main_loop_quit(pt_to_loop(pt));
lws_gs_destroy(pt->glib.sigint);
lws_gs_destroy(ptpr->sigint);
g_main_loop_unref(pt_to_loop(pt));
}
@ -464,7 +475,7 @@ elops_wsi_logical_close_glib(struct lws *wsi)
return 0;
}
struct lws_event_loop_ops event_loop_ops_glib = {
static const struct lws_event_loop_ops event_loop_ops_glib = {
/* name */ "glib",
/* init_context */ elops_init_context_glib,
/* destroy_context1 */ NULL,
@ -481,4 +492,22 @@ struct lws_event_loop_ops event_loop_ops_glib = {
/* destroy wsi */ elops_destroy_wsi_glib,
/* flags */ LELOF_DESTROY_FINAL,
/* evlib_size_ctx */ 0,
/* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_glib),
/* evlib_size_vh */ 0,
/* evlib_size_wsi */ sizeof(struct lws_io_watcher_glib),
};
#if defined(LWS_WITH_EVLIB_PLUGINS)
LWS_VISIBLE
#endif
const lws_plugin_evlib_t evlib_glib = {
.hdr = {
"glib event loop",
"lws_evlib_plugin",
LWS_PLUGIN_API_MAGIC
},
.ops = &event_loop_ops_glib
};

View file

@ -41,6 +41,8 @@ struct lws_pt_eventlibs_glib {
lws_glib_tag_t hrtimer;
lws_glib_tag_t sigint;
lws_glib_tag_t idle;
//struct lws_signal_watcher_libuv w_sigint;
};
struct lws_io_watcher_glib_subclass {
@ -55,10 +57,11 @@ struct lws_io_watcher_glib_subclass {
struct lws_io_watcher_glib {
struct lws_io_watcher_glib_subclass *source; /* these are created and destroyed by glib */
struct lws_context *context;
uint8_t actual_events;
};
struct lws_context_eventlibs_glib {
//int placeholder;
struct lws_wsi_eventlibs_glib {
struct lws_io_watcher_glib w_read;
};
extern struct lws_event_loop_ops event_loop_ops_glib;

View file

@ -40,7 +40,6 @@ endif()
message("libev include dir: ${LIBEV_INCLUDE_DIRS}")
message("libev libraries: ${LIBEV_LIBRARIES}")
include_directories("${LIBEV_INCLUDE_DIRS}")
list(APPEND LIB_LIST ${LIBEV_LIBRARIES})
if ("${LWS_LIBEV_LIBRARIES}" STREQUAL "" OR "${LWS_LIBEV_INCLUDE_DIRS}" STREQUAL "")
else()
@ -48,13 +47,26 @@ else()
set(LIBEV_INCLUDE_DIRS ${LWS_LIBEV_INCLUDE_DIRS})
endif()
list(APPEND SOURCES
event-libs/libev/libev.c)
if (LWS_WITH_EVLIB_PLUGINS)
create_evlib_plugin(
evlib_ev
libev.c
private-lib-event-libs-libev.h
${LIBEV_LIBRARIES})
else()
list(APPEND LIB_LIST ${LIBEV_LIBRARIES})
list(APPEND SOURCES
event-libs/libev/libev.c)
# see README.build.md for discussion of why of the supported event libs,
# only libev cannot cope with -Werror
set_source_files_properties(event-libs/libev/libev.c
PROPERTIES COMPILE_FLAGS "-Wno-error" )
set_source_files_properties(event-libs/libev/libev.c
PROPERTIES COMPILE_FLAGS "-Wno-error" )
endif()
set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST})
CHECK_C_SOURCE_COMPILES(

View file

@ -1,7 +1,7 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@ -23,20 +23,26 @@
*/
#include "private-lib-core.h"
#include "private-lib-event-libs-libev.h"
#define pt_to_priv_ev(_pt) ((struct lws_pt_eventlibs_libev *)(_pt)->evlib_pt)
#define vh_to_priv_ev(_vh) ((struct lws_vh_eventlibs_libev *)(_vh)->evlib_vh)
#define wsi_to_priv_ev(_w) ((struct lws_wsi_eventlibs_libev *)(_w)->evlib_wsi)
static void
lws_ev_hrtimer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)
{
struct lws_context_per_thread *pt =
(struct lws_context_per_thread *)watcher->data;
struct lws_pt_eventlibs_libev *ptpr = lws_container_of(watcher,
struct lws_pt_eventlibs_libev, hrtimer);
struct lws_context_per_thread *pt = ptpr->pt;
lws_usec_t us;
lws_pt_lock(pt, __func__);
us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
lws_now_usecs());
if (us) {
ev_timer_set(&pt->ev.hrtimer, ((float)us) / 1000000.0, 0);
ev_timer_start(pt->ev.io_loop, &pt->ev.hrtimer);
ev_timer_set(&ptpr->hrtimer, ((float)us) / 1000000.0, 0);
ev_timer_start(ptpr->io_loop, &ptpr->hrtimer);
}
lws_pt_unlock(pt);
}
@ -44,10 +50,11 @@ lws_ev_hrtimer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)
static void
lws_ev_idle_cb(struct ev_loop *loop, struct ev_idle *handle, int revents)
{
struct lws_context_per_thread *pt = lws_container_of(handle,
struct lws_context_per_thread, ev.idle);
lws_usec_t us;
struct lws_pt_eventlibs_libev *ptpr = lws_container_of(handle,
struct lws_pt_eventlibs_libev, idle);
struct lws_context_per_thread *pt = ptpr->pt;
int reschedule = 0;
lws_usec_t us;
lws_service_do_ripe_rxflow(pt);
@ -64,8 +71,8 @@ lws_ev_idle_cb(struct ev_loop *loop, struct ev_idle *handle, int revents)
us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
lws_now_usecs());
if (us) {
ev_timer_set(&pt->ev.hrtimer, ((float)us) / 1000000.0, 0);
ev_timer_start(pt->ev.io_loop, &pt->ev.hrtimer);
ev_timer_set(&ptpr->hrtimer, ((float)us) / 1000000.0, 0);
ev_timer_start(ptpr->io_loop, &ptpr->hrtimer);
}
lws_pt_unlock(pt);
@ -80,9 +87,10 @@ lws_ev_idle_cb(struct ev_loop *loop, struct ev_idle *handle, int revents)
static void
lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
struct lws_io_watcher *lws_io = lws_container_of(watcher,
struct lws_io_watcher, ev.watcher);
struct lws_io_watcher_libev *lws_io = lws_container_of(watcher,
struct lws_io_watcher_libev, watcher);
struct lws_context *context = lws_io->context;
struct lws_pt_eventlibs_libev *ptpr;
struct lws_context_per_thread *pt;
struct lws_pollfd eventfd;
struct lws *wsi;
@ -105,10 +113,11 @@ lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
wsi = wsi_from_fd(context, watcher->fd);
pt = &context->pt[(int)wsi->tsi];
ptpr = pt_to_priv_ev(pt);
lws_service_fd_tsi(context, &eventfd, (int)wsi->tsi);
ev_idle_start(pt->ev.io_loop, &pt->ev.idle);
ev_idle_start(ptpr->io_loop, &ptpr->idle);
}
void
@ -128,7 +137,8 @@ static int
elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
{
struct lws_context_per_thread *pt = &context->pt[tsi];
struct ev_signal *w_sigint = &context->pt[tsi].w_sigint.ev.watcher;
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;
@ -137,6 +147,8 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
lwsl_info("%s: loop %p\n", __func__, _loop);
ptpr->pt = pt;
if (!loop)
loop = ev_loop_new(0);
else
@ -148,7 +160,7 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
return -1;
}
pt->ev.io_loop = loop;
ptpr->io_loop = loop;
/*
* Initialize the accept w_accept with all the listening sockets
@ -156,13 +168,17 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
*/
while (vh) {
if (vh->lserv_wsi) {
vh->lserv_wsi->w_read.context = context;
vh->w_accept.context = context;
struct lws_wsi_eventlibs_libev *w =
wsi_to_priv_ev(vh->lserv_wsi);
ev_io_init(&vh->w_accept.ev.watcher, lws_accept_cb,
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->w_accept.ev.watcher);
ev_io_start(loop, &vh_to_priv_ev(vh)->w_accept.watcher);
}
vh = vh->vhost_next;
}
@ -212,10 +228,10 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
lwsl_info(" libev backend: %s\n", backend_name);
(void)backend_name;
ev_timer_init(&pt->ev.hrtimer, lws_ev_hrtimer_cb, 0, 0);
pt->ev.hrtimer.data = pt;
ev_timer_init(&ptpr->hrtimer, lws_ev_hrtimer_cb, 0, 0);
ptpr->hrtimer.data = pt;
ev_idle_init(&pt->ev.idle, lws_ev_idle_cb);
ev_idle_init(&ptpr->idle, lws_ev_idle_cb);
return status;
}
@ -224,21 +240,23 @@ 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(pt->ev.io_loop, &vh->w_accept.ev.watcher);
ev_io_stop(ptpr->io_loop,
&vh_to_priv_ev(vh)->w_accept.watcher);
vh = vh->vhost_next;
}
/* static assets */
ev_timer_stop(pt->ev.io_loop, &pt->ev.hrtimer);
ev_idle_stop(pt->ev.io_loop, &pt->ev.idle);
ev_timer_stop(ptpr->io_loop, &ptpr->hrtimer);
ev_idle_stop(ptpr->io_loop, &ptpr->idle);
if (!pt->event_loop_foreign)
ev_signal_stop(pt->ev.io_loop, &pt->w_sigint.ev.watcher);
ev_signal_stop(ptpr->io_loop, &ptpr->w_sigint.watcher);
}
static int
@ -250,7 +268,7 @@ elops_init_context_ev(struct lws_context *context,
context->eventlib_signal_cb = info->signal_cb;
for (n = 0; n < context->count_threads; n++)
context->pt[n].w_sigint.context = context;
pt_to_priv_ev(&context->pt[n])->w_sigint.context = context;
return 0;
}
@ -258,18 +276,21 @@ elops_init_context_ev(struct lws_context *context,
static int
elops_accept_ev(struct lws *wsi)
{
struct lws_wsi_eventlibs_libev *w = wsi_to_priv_ev(wsi);
int fd;
lwsl_notice("%s\n", __func__);
if (wsi->role_ops->file_handle)
fd = wsi->desc.filefd;
else
fd = wsi->desc.sockfd;
wsi->w_read.context = wsi->a.context;
wsi->w_write.context = wsi->a.context;
w->w_read.context = wsi->a.context;
w->w_write.context = wsi->a.context;
ev_io_init(&wsi->w_read.ev.watcher, lws_accept_cb, fd, EV_READ);
ev_io_init(&wsi->w_write.ev.watcher, lws_accept_cb, fd, EV_WRITE);
ev_io_init(&w->w_read.watcher, lws_accept_cb, fd, EV_READ);
ev_io_init(&w->w_write.watcher, lws_accept_cb, fd, EV_WRITE);
return 0;
}
@ -278,8 +299,14 @@ static void
elops_io_ev(struct lws *wsi, int flags)
{
struct lws_context_per_thread *pt = &wsi->a.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);
if (!pt->ev.io_loop || pt->is_destroyed)
lwsl_notice("%s: wsi %p %s flags 0x%x %p %d\n", __func__,
wsi, wsi->role_ops->name, flags,
ptpr->io_loop, pt->is_destroyed);
if (!ptpr->io_loop || pt->is_destroyed)
return;
assert((flags & (LWS_EV_START | LWS_EV_STOP)) &&
@ -287,14 +314,14 @@ elops_io_ev(struct lws *wsi, int flags)
if (flags & LWS_EV_START) {
if (flags & LWS_EV_WRITE)
ev_io_start(pt->ev.io_loop, &wsi->w_write.ev.watcher);
ev_io_start(ptpr->io_loop, &w->w_write.watcher);
if (flags & LWS_EV_READ)
ev_io_start(pt->ev.io_loop, &wsi->w_read.ev.watcher);
ev_io_start(ptpr->io_loop, &w->w_read.watcher);
} else {
if (flags & LWS_EV_WRITE)
ev_io_stop(pt->ev.io_loop, &wsi->w_write.ev.watcher);
ev_io_stop(ptpr->io_loop, &w->w_write.watcher);
if (flags & LWS_EV_READ)
ev_io_stop(pt->ev.io_loop, &wsi->w_read.ev.watcher);
ev_io_stop(ptpr->io_loop, &w->w_read.watcher);
}
if (pt->destroy_self)
@ -304,14 +331,15 @@ elops_io_ev(struct lws *wsi, int flags)
static void
elops_run_pt_ev(struct lws_context *context, int tsi)
{
if (context->pt[tsi].ev.io_loop)
ev_run(context->pt[tsi].ev.io_loop, 0);
if (pt_to_priv_ev(&context->pt[tsi])->io_loop)
ev_run(pt_to_priv_ev(&context->pt[tsi])->io_loop, 0);
}
static int
elops_destroy_context2_ev(struct lws_context *context)
{
struct lws_context_per_thread *pt;
struct lws_pt_eventlibs_libev *ptpr;
int n, m;
lwsl_debug("%s\n", __func__);
@ -320,21 +348,22 @@ elops_destroy_context2_ev(struct lws_context *context)
int budget = 1000;
pt = &context->pt[n];
ptpr = pt_to_priv_ev(pt);
/* only for internal loops... */
if (pt->event_loop_foreign || !pt->ev.io_loop)
if (pt->event_loop_foreign || !ptpr->io_loop)
continue;
if (!context->finalize_destroy_after_internal_loops_stopped) {
ev_break(pt->ev.io_loop, EVBREAK_ONE);
ev_break(ptpr->io_loop, EVBREAK_ONE);
continue;
}
while (budget-- &&
(m = ev_run(pt->ev.io_loop, 0)))
(m = ev_run(ptpr->io_loop, 0)))
;
ev_loop_destroy(pt->ev.io_loop);
ev_loop_destroy(ptpr->io_loop);
}
return 0;
@ -343,6 +372,7 @@ elops_destroy_context2_ev(struct lws_context *context)
static int
elops_init_vhost_listen_wsi_ev(struct lws *wsi)
{
struct lws_wsi_eventlibs_libev *w;
int fd;
if (!wsi) {
@ -350,16 +380,17 @@ elops_init_vhost_listen_wsi_ev(struct lws *wsi)
return 0;
}
wsi->w_read.context = wsi->a.context;
wsi->w_write.context = wsi->a.context;
w = wsi_to_priv_ev(wsi);
w->w_read.context = wsi->a.context;
w->w_write.context = wsi->a.context;
if (wsi->role_ops->file_handle)
fd = wsi->desc.filefd;
else
fd = wsi->desc.sockfd;
ev_io_init(&wsi->w_read.ev.watcher, lws_accept_cb, fd, EV_READ);
ev_io_init(&wsi->w_write.ev.watcher, lws_accept_cb, fd, EV_WRITE);
ev_io_init(&w->w_read.watcher, lws_accept_cb, fd, EV_READ);
//ev_io_init(&w->w_write.watcher, lws_accept_cb, fd, EV_WRITE);
elops_io_ev(wsi, LWS_EV_START | LWS_EV_READ);
@ -370,12 +401,14 @@ static void
elops_destroy_wsi_ev(struct lws *wsi)
{
struct lws_context_per_thread *pt = &wsi->a.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);
ev_io_stop(pt->ev.io_loop, &wsi->w_read.ev.watcher);
ev_io_stop(pt->ev.io_loop, &wsi->w_write.ev.watcher);
ev_io_stop(ptpr->io_loop, &w->w_read.watcher);
ev_io_stop(ptpr->io_loop, &w->w_write.watcher);
}
struct lws_event_loop_ops event_loop_ops_ev = {
static const struct lws_event_loop_ops event_loop_ops_ev = {
/* name */ "libev",
/* init_context */ elops_init_context_ev,
/* destroy_context1 */ NULL,
@ -392,4 +425,22 @@ struct lws_event_loop_ops event_loop_ops_ev = {
/* destroy wsi */ elops_destroy_wsi_ev,
/* flags */ 0,
/* evlib_size_ctx */ 0,
/* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_libev),
/* evlib_size_vh */ sizeof(struct lws_vh_eventlibs_libev),
/* evlib_size_wsi */ sizeof(struct lws_wsi_eventlibs_libev),
};
#if defined(LWS_WITH_EVLIB_PLUGINS)
LWS_VISIBLE
#endif
const lws_plugin_evlib_t evlib_ev = {
.hdr = {
"libev event loop",
"lws_evlib_plugin",
LWS_PLUGIN_API_MAGIC
},
.ops = &event_loop_ops_ev
};

View file

@ -33,22 +33,30 @@
(--(LWS_UV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x)-> \
count_event_loop_static_asset_handles))
struct lws_signal_watcher_libev {
ev_signal watcher;
struct lws_context *context;
};
struct lws_pt_eventlibs_libev {
struct ev_loop *io_loop;
struct ev_timer hrtimer;
struct ev_idle idle;
struct lws_signal_watcher_libev w_sigint;
struct lws_context_per_thread *pt;
};
struct lws_io_watcher_libev {
ev_io watcher;
struct lws_context *context;
};
struct lws_signal_watcher_libev {
ev_signal watcher;
struct lws_vh_eventlibs_libev {
struct lws_io_watcher_libev w_accept;
};
struct lws_context_eventlibs_libev {
int placeholder;
struct lws_wsi_eventlibs_libev {
struct lws_io_watcher_libev w_read;
struct lws_io_watcher_libev w_write;
};
extern struct lws_event_loop_ops event_loop_ops_ev;

View file

@ -40,18 +40,29 @@ endif()
message("libevent include dir: ${LIBEVENT_INCLUDE_DIRS}")
message("libevent libraries: ${LIBEVENT_LIBRARIES}")
include_directories("${LIBEVENT_INCLUDE_DIRS}")
list(APPEND LIB_LIST ${LIBEVENT_LIBRARIES})
if ("${LWS_LIBEVENT_LIBRARIES}" STREQUAL "" OR "${LWS_LIBEVENT_INCLUDE_DIRS}" STREQUAL "")
else()
set(LIBEVENT_LIBRARIES ${LWS_LIBEVENT_LIBRARIES})
set(LIBEVENT_INCLUDE_DIRS ${LWS_LIBEVENT_INCLUDE_DIRS})
set(LIBEVENT_FOUND 1 PARENT_SCOPE)
endif()
if (LWS_WITH_NETWORK)
list(APPEND SOURCES
event-libs/libevent/libevent.c)
if (LWS_WITH_EVLIB_PLUGINS)
create_evlib_plugin(evlib_event
libevent.c
private-lib-event-libs-libevent.h
${LIBEVENT_LIBRARIES})
else()
list(APPEND LIB_LIST ${LIBEVENT_LIBRARIES})
set(LIBEVENT_FOUND 1 PARENT_SCOPE)
if (LWS_WITH_NETWORK)
list(APPEND SOURCES
event-libs/libevent/libevent.c)
endif()
endif()
#

View file

@ -23,11 +23,16 @@
*/
#include "private-lib-core.h"
#include "private-lib-event-libs-libevent.h"
#define pt_to_priv_event(_pt) ((struct lws_pt_eventlibs_libevent *)(_pt)->evlib_pt)
#define wsi_to_priv_event(_w) ((struct lws_wsi_eventlibs_libevent *)(_w)->evlib_wsi)
static void
lws_event_hrtimer_cb(int fd, short event, void *p)
{
struct lws_context_per_thread *pt = (struct lws_context_per_thread *)p;
struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
struct timeval tv;
lws_usec_t us;
@ -37,7 +42,7 @@ lws_event_hrtimer_cb(int fd, short event, void *p)
if (us) {
tv.tv_sec = us / LWS_US_PER_SEC;
tv.tv_usec = us - (tv.tv_sec * LWS_US_PER_SEC);
evtimer_add(pt->event.hrtimer, &tv);
evtimer_add(ptpr->hrtimer, &tv);
}
lws_pt_unlock(pt);
}
@ -46,6 +51,7 @@ static void
lws_event_idle_timer_cb(int fd, short event, void *p)
{
struct lws_context_per_thread *pt = (struct lws_context_per_thread *)p;
struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
struct timeval tv;
lws_usec_t us;
@ -66,7 +72,7 @@ lws_event_idle_timer_cb(int fd, short event, void *p)
tv.tv_sec = 0;
tv.tv_usec = 1000;
evtimer_add(pt->event.idle_timer, &tv);
evtimer_add(ptpr->idle_timer, &tv);
return;
}
@ -82,11 +88,10 @@ lws_event_idle_timer_cb(int fd, short event, void *p)
if (us) {
tv.tv_sec = us / LWS_US_PER_SEC;
tv.tv_usec = us - (tv.tv_sec * LWS_US_PER_SEC);
evtimer_add(pt->event.hrtimer, &tv);
evtimer_add(ptpr->hrtimer, &tv);
}
lws_pt_unlock(pt);
if (pt->destroy_self)
lws_context_destroy(pt->context);
}
@ -94,7 +99,8 @@ lws_event_idle_timer_cb(int fd, short event, void *p)
static void
lws_event_cb(evutil_socket_t sock_fd, short revents, void *ctx)
{
struct lws_io_watcher *lws_io = (struct lws_io_watcher *)ctx;
struct lws_signal_watcher_libevent *lws_io =
(struct lws_signal_watcher_libevent *)ctx;
struct lws_context *context = lws_io->context;
struct lws_context_per_thread *pt;
struct lws_pollfd eventfd;
@ -145,7 +151,7 @@ lws_event_cb(evutil_socket_t sock_fd, short revents, void *ctx)
tv.tv_sec = 0;
tv.tv_usec = 1000;
evtimer_add(pt->event.idle_timer, &tv);
evtimer_add(pt_to_priv_event(pt)->idle_timer, &tv);
}
void
@ -161,16 +167,16 @@ lws_event_sigint_cb(evutil_socket_t sock_fd, short revents, void *ctx)
return;
}
if (!pt->event_loop_foreign)
event_base_loopbreak(pt->event.io_loop);
event_base_loopbreak(pt_to_priv_event(pt)->io_loop);
}
static int
elops_init_pt_event(struct lws_context *context, void *_loop, int tsi)
{
struct lws_vhost *vh = context->vhost_list;
struct event_base *loop = (struct event_base *)_loop;
struct lws_context_per_thread *pt = &context->pt[tsi];
struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
lwsl_info("%s: loop %p\n", __func__, _loop);
@ -185,7 +191,7 @@ elops_init_pt_event(struct lws_context *context, void *_loop, int tsi)
return -1;
}
pt->event.io_loop = loop;
ptpr->io_loop = loop;
/*
* Initialize all events with the listening sockets
@ -194,23 +200,26 @@ elops_init_pt_event(struct lws_context *context, void *_loop, int tsi)
while (vh) {
if (vh->lserv_wsi) {
vh->lserv_wsi->w_read.context = context;
vh->lserv_wsi->w_read.event.watcher = event_new(
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,
&vh->lserv_wsi->w_read);
event_add(vh->lserv_wsi->w_read.event.watcher, NULL);
vh->lserv_wsi->w_read.event.set = 1;
w_read);
event_add(w_read->watcher, NULL);
w_read->set = 1;
}
vh = vh->vhost_next;
}
/* static event loop objects */
pt->event.hrtimer = event_new(loop, -1, EV_PERSIST,
ptpr->hrtimer = event_new(loop, -1, EV_PERSIST,
lws_event_hrtimer_cb, pt);
pt->event.idle_timer = event_new(loop, -1, 0,
ptpr->idle_timer = event_new(loop, -1, 0,
lws_event_idle_timer_cb, pt);
/* Register the signal watcher unless it's a foreign loop */
@ -218,9 +227,9 @@ elops_init_pt_event(struct lws_context *context, void *_loop, int tsi)
if (pt->event_loop_foreign)
return 0;
pt->w_sigint.event.watcher = evsignal_new(loop, SIGINT,
ptpr->w_sigint.watcher = evsignal_new(loop, SIGINT,
lws_event_sigint_cb, pt);
event_add(pt->w_sigint.event.watcher, NULL);
event_add(ptpr->w_sigint.watcher, NULL);
return 0;
}
@ -234,7 +243,7 @@ elops_init_context_event(struct lws_context *context,
context->eventlib_signal_cb = info->signal_cb;
for (n = 0; n < context->count_threads; n++)
context->pt[n].w_sigint.context = context;
pt_to_priv_event(&context->pt[n])->w_sigint.context = context;
return 0;
}
@ -244,23 +253,26 @@ elops_accept_event(struct lws *wsi)
{
struct lws_context *context = lws_get_context(wsi);
struct lws_context_per_thread *pt;
struct lws_pt_eventlibs_libevent *ptpr;
struct lws_wsi_eventlibs_libevent *wpr = wsi_to_priv_event(wsi);
int fd;
wsi->w_read.context = context;
wsi->w_write.context = context;
wpr->w_read.context = context;
wpr->w_write.context = context;
// Initialize the event
pt = &context->pt[(int)wsi->tsi];
ptpr = pt_to_priv_event(pt);
if (wsi->role_ops->file_handle)
fd = wsi->desc.filefd;
else
fd = wsi->desc.sockfd;
wsi->w_read.event.watcher = event_new(pt->event.io_loop, fd,
(EV_READ | EV_PERSIST), lws_event_cb, &wsi->w_read);
wsi->w_write.event.watcher = event_new(pt->event.io_loop, fd,
(EV_WRITE | EV_PERSIST), lws_event_cb, &wsi->w_write);
wpr->w_read.watcher = event_new(ptpr->io_loop, fd,
(EV_READ | EV_PERSIST), lws_event_cb, &wpr->w_read);
wpr->w_write.watcher = event_new(ptpr->io_loop, fd,
(EV_WRITE | EV_PERSIST), lws_event_cb, &wpr->w_write);
return 0;
}
@ -269,8 +281,10 @@ static void
elops_io_event(struct lws *wsi, int flags)
{
struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
struct lws_wsi_eventlibs_libevent *wpr = wsi_to_priv_event(wsi);
if (!pt->event.io_loop || wsi->a.context->being_destroyed ||
if (!ptpr->io_loop || wsi->a.context->being_destroyed ||
pt->is_destroyed)
return;
@ -278,24 +292,24 @@ elops_io_event(struct lws *wsi, int flags)
(flags & (LWS_EV_READ | LWS_EV_WRITE)));
if (flags & LWS_EV_START) {
if ((flags & LWS_EV_WRITE) && !wsi->w_write.event.set) {
event_add(wsi->w_write.event.watcher, NULL);
wsi->w_write.event.set = 1;
if ((flags & LWS_EV_WRITE) && !wpr->w_write.set) {
event_add(wpr->w_write.watcher, NULL);
wpr->w_write.set = 1;
}
if ((flags & LWS_EV_READ) && !wsi->w_read.event.set) {
event_add(wsi->w_read.event.watcher, NULL);
wsi->w_read.event.set = 1;
if ((flags & LWS_EV_READ) && !wpr->w_read.set) {
event_add(wpr->w_read.watcher, NULL);
wpr->w_read.set = 1;
}
} else {
if ((flags & LWS_EV_WRITE) && wsi->w_write.event.set) {
event_del(wsi->w_write.event.watcher);
wsi->w_write.event.set = 0;
if ((flags & LWS_EV_WRITE) && wpr->w_write.set) {
event_del(wpr->w_write.watcher);
wpr->w_write.set = 0;
}
if ((flags & LWS_EV_READ) && wsi->w_read.event.set) {
event_del(wsi->w_read.event.watcher);
wsi->w_read.event.set = 0;
if ((flags & LWS_EV_READ) && wpr->w_read.set) {
event_del(wpr->w_read.watcher);
wpr->w_read.set = 0;
}
}
}
@ -304,19 +318,21 @@ static void
elops_run_pt_event(struct lws_context *context, int tsi)
{
/* Run / Dispatch the event_base loop */
if (context->pt[tsi].event.io_loop)
event_base_dispatch(context->pt[tsi].event.io_loop);
if (pt_to_priv_event(&context->pt[tsi])->io_loop)
event_base_dispatch(
pt_to_priv_event(&context->pt[tsi])->io_loop);
}
static void
elops_destroy_pt_event(struct lws_context *context, int tsi)
{
struct lws_context_per_thread *pt = &context->pt[tsi];
struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
struct lws_vhost *vh = context->vhost_list;
lwsl_info("%s\n", __func__);
if (!pt->event.io_loop)
if (!ptpr->io_loop)
return;
/*
@ -324,21 +340,24 @@ elops_destroy_pt_event(struct lws_context *context, int tsi)
*/
while (vh) {
if (vh->lserv_wsi) {
event_free(vh->lserv_wsi->w_read.event.watcher);
vh->lserv_wsi->w_read.event.watcher = NULL;
event_free(vh->lserv_wsi->w_write.event.watcher);
vh->lserv_wsi->w_write.event.watcher = NULL;
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;
}
event_free(pt->event.hrtimer);
event_free(pt->event.idle_timer);
event_free(ptpr->hrtimer);
event_free(ptpr->idle_timer);
if (!pt->event_loop_foreign) {
event_del(pt->w_sigint.event.watcher);
event_free(pt->w_sigint.event.watcher);
event_base_loopexit(pt->event.io_loop, NULL);
event_del(ptpr->w_sigint.watcher);
event_free(ptpr->w_sigint.watcher);
event_base_loopexit(ptpr->io_loop, NULL);
// event_base_free(pt->event.io_loop);
// pt->event.io_loop = NULL;
lwsl_notice("%s: set to exit loop\n", __func__);
@ -349,6 +368,7 @@ static void
elops_destroy_wsi_event(struct lws *wsi)
{
struct lws_context_per_thread *pt;
struct lws_wsi_eventlibs_libevent *w;
if (!wsi)
return;
@ -357,14 +377,16 @@ elops_destroy_wsi_event(struct lws *wsi)
if (pt->is_destroyed)
return;
if (wsi->w_read.event.watcher) {
event_free(wsi->w_read.event.watcher);
wsi->w_read.event.watcher = NULL;
w = wsi_to_priv_event(wsi);
if (w->w_read.watcher) {
event_free(w->w_read.watcher);
w->w_read.watcher = NULL;
}
if (wsi->w_write.event.watcher) {
event_free(wsi->w_write.event.watcher);
wsi->w_write.event.watcher = NULL;
if (w->w_write.watcher) {
event_free(w->w_write.watcher);
w->w_write.watcher = NULL;
}
}
@ -380,6 +402,8 @@ static int
elops_init_vhost_listen_wsi_event(struct lws *wsi)
{
struct lws_context_per_thread *pt;
struct lws_pt_eventlibs_libevent *ptpr;
struct lws_wsi_eventlibs_libevent *w;
int fd;
if (!wsi) {
@ -387,22 +411,24 @@ elops_init_vhost_listen_wsi_event(struct lws *wsi)
return 0;
}
wsi->w_read.context = wsi->a.context;
wsi->w_write.context = wsi->a.context;
w = wsi_to_priv_event(wsi);
w->w_read.context = wsi->a.context;
w->w_write.context = wsi->a.context;
pt = &wsi->a.context->pt[(int)wsi->tsi];
ptpr = pt_to_priv_event(pt);
if (wsi->role_ops->file_handle)
fd = wsi->desc.filefd;
else
fd = wsi->desc.sockfd;
wsi->w_read.event.watcher = event_new(pt->event.io_loop, fd,
(EV_READ | EV_PERSIST),
lws_event_cb, &wsi->w_read);
wsi->w_write.event.watcher = event_new(pt->event.io_loop, fd,
(EV_WRITE | EV_PERSIST),
lws_event_cb, &wsi->w_write);
w->w_read.watcher = event_new(ptpr->io_loop, fd, (EV_READ | EV_PERSIST),
lws_event_cb, &w->w_read);
w->w_write.watcher = event_new(ptpr->io_loop, fd,
(EV_WRITE | EV_PERSIST),
lws_event_cb, &w->w_write);
elops_io_event(wsi, LWS_EV_START | LWS_EV_READ);
@ -413,6 +439,7 @@ static int
elops_destroy_context2_event(struct lws_context *context)
{
struct lws_context_per_thread *pt;
struct lws_pt_eventlibs_libevent *ptpr;
int n, m;
lwsl_debug("%s: in\n", __func__);
@ -421,31 +448,31 @@ elops_destroy_context2_event(struct lws_context *context)
int budget = 1000;
pt = &context->pt[n];
ptpr = pt_to_priv_event(pt);
/* only for internal loops... */
if (pt->event_loop_foreign || !pt->event.io_loop)
if (pt->event_loop_foreign || !ptpr->io_loop)
continue;
if (!context->finalize_destroy_after_internal_loops_stopped) {
event_base_loopexit(pt->event.io_loop, NULL);
event_base_loopexit(ptpr->io_loop, NULL);
continue;
}
while (budget-- &&
(m = event_base_loop(pt->event.io_loop, EVLOOP_NONBLOCK)))
(m = event_base_loop(ptpr->io_loop, EVLOOP_NONBLOCK)))
;
#if 0
if (m) {
lwsl_err("%s: tsi %d: NOT everything closed\n",
__func__, n);
event_base_dump_events(pt->event.io_loop, stderr);
event_base_dump_events(ptpr->io_loop, stderr);
} else
lwsl_debug("%s: %d: everything closed OK\n", __func__, n);
#endif
lwsl_err("%s: event_base_free\n", __func__);
event_base_free(pt->event.io_loop);
pt->event.io_loop = NULL;
event_base_free(ptpr->io_loop);
ptpr->io_loop = NULL;
}
lwsl_debug("%s: out\n", __func__);
@ -453,7 +480,7 @@ elops_destroy_context2_event(struct lws_context *context)
return 0;
}
struct lws_event_loop_ops event_loop_ops_event = {
static const struct lws_event_loop_ops event_loop_ops_event = {
/* name */ "libevent",
/* init_context */ elops_init_context_event,
/* destroy_context1 */ NULL,
@ -470,4 +497,22 @@ struct lws_event_loop_ops event_loop_ops_event = {
/* destroy wsi */ elops_destroy_wsi_event,
/* flags */ 0,
/* evlib_size_ctx */ 0,
/* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_libevent),
/* evlib_size_vh */ 0,
/* evlib_size_wsi */ sizeof(struct lws_wsi_eventlibs_libevent),
};
#if defined(LWS_WITH_EVLIB_PLUGINS)
LWS_VISIBLE
#endif
const lws_plugin_evlib_t evlib_event = {
.hdr = {
"libevent event loop",
"lws_evlib_plugin",
LWS_PLUGIN_API_MAGIC
},
.ops = &event_loop_ops_event
};

View file

@ -24,23 +24,26 @@
#include <event2/event.h>
struct lws_signal_watcher_libevent {
struct event *watcher;
struct lws_context *context;
};
struct lws_pt_eventlibs_libevent {
struct event_base *io_loop;
struct event *hrtimer;
struct event *idle_timer;
struct lws_signal_watcher_libevent w_sigint;
};
struct lws_io_watcher_libevent {
struct event *watcher;
struct lws_context *context;
uint8_t actual_events;
char set;
};
struct lws_signal_watcher_libevent {
struct event *watcher;
struct lws_wsi_eventlibs_libevent {
struct lws_io_watcher_libevent w_read;
struct lws_io_watcher_libevent w_write;
};
struct lws_context_eventlibs_libevent {
int placeholder;
};
extern struct lws_event_loop_ops event_loop_ops_event;

View file

@ -47,7 +47,6 @@ message("libuv include dir: ${LIBUV_INCLUDE_DIRS}")
message("libuv libraries: ${LIBUV_LIBRARIES}")
include_directories("${LIBUV_INCLUDE_DIRS}")
list(APPEND LIB_LIST ${LIBUV_LIBRARIES})
CHECK_INCLUDE_FILE(uv-version.h LWS_HAVE_UV_VERSION_H)
# libuv changed the location in 1.21.0. Retain both
@ -55,11 +54,27 @@ CHECK_INCLUDE_FILE(uv-version.h LWS_HAVE_UV_VERSION_H)
if (NOT LWS_HAVE_UV_VERSION_H)
CHECK_INCLUDE_FILE(uv/version.h LWS_HAVE_NEW_UV_VERSION_H)
endif()
if (LWS_WITH_EVLIB_PLUGINS AND LWS_WITH_LIBUV)
if (LWS_WITH_NETWORK)
list(APPEND SOURCES
event-libs/libuv/libuv.c)
endif()
create_evlib_plugin(evlib_uv
libuv.c
private-lib-event-libs-libuv.h
${LIBUV_LIBRARIES})
endif()
# wanting libuv in the library is a separate question than
# wanting libuv as a selectable event loop plugin
# we only came here because LWS_WITH_LIBUV or LWS_WITH_LIBUV_INTERNAL
if ((NOT LWS_WITH_EVLIB_PLUGINS) OR LWS_WITH_LIBUV_INTERNAL)
list(APPEND LIB_LIST ${LIBUV_LIBRARIES})
if (LWS_WITH_NETWORK)
list(APPEND SOURCES
event-libs/libuv/libuv.c)
endif()
endif()
#
# Keep explicit parent scope exports at end

View file

@ -23,6 +23,10 @@
*/
#include "private-lib-core.h"
#include "private-lib-event-libs-libuv.h"
#define pt_to_priv_uv(_pt) ((struct lws_pt_eventlibs_libuv *)(_pt)->evlib_pt)
#define wsi_to_priv_uv(_w) ((struct lws_wsi_eventlibs_libuv *)(_w)->evlib_wsi)
static void
lws_uv_sultimer_cb(uv_timer_t *timer
@ -31,15 +35,17 @@ lws_uv_sultimer_cb(uv_timer_t *timer
#endif
)
{
struct lws_context_per_thread *pt = lws_container_of(timer,
struct lws_context_per_thread, uv.sultimer);
struct lws_pt_eventlibs_libuv *ptpr = lws_container_of(timer,
struct lws_pt_eventlibs_libuv, sultimer);
struct lws_context_per_thread *pt = lws_container_of(ptpr,
struct lws_context_per_thread, evlib_pt);
lws_usec_t us;
lws_pt_lock(pt, __func__);
us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
lws_now_usecs());
if (us)
uv_timer_start(&pt->uv.sultimer, lws_uv_sultimer_cb,
uv_timer_start(&pt_to_priv_uv(pt)->sultimer, lws_uv_sultimer_cb,
LWS_US_TO_MS(us), 0);
lws_pt_unlock(pt);
}
@ -50,9 +56,10 @@ lws_uv_idle(uv_idle_t *handle
, int status
#endif
)
{
struct lws_context_per_thread *pt = lws_container_of(handle,
struct lws_context_per_thread, uv.idle);
{ struct lws_pt_eventlibs_libuv *ptpr = lws_container_of(handle,
struct lws_pt_eventlibs_libuv, idle);
struct lws_context_per_thread *pt = lws_container_of(ptpr,
struct lws_context_per_thread, evlib_pt);
lws_usec_t us;
lws_service_do_ripe_rxflow(pt);
@ -70,7 +77,7 @@ lws_uv_idle(uv_idle_t *handle
us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
lws_now_usecs());
if (us)
uv_timer_start(&pt->uv.sultimer, lws_uv_sultimer_cb,
uv_timer_start(&pt_to_priv_uv(pt)->sultimer, lws_uv_sultimer_cb,
LWS_US_TO_MS(us), 0);
lws_pt_unlock(pt);
@ -126,7 +133,7 @@ lws_io_cb(uv_poll_t *watcher, int status, int revents)
return;
}
uv_idle_start(&pt->uv.idle, lws_uv_idle);
uv_idle_start(&pt_to_priv_uv(pt)->idle, lws_uv_idle);
}
/*
@ -161,7 +168,7 @@ lws_libuv_stop(struct lws_context *context)
pt = &context->pt[m];
if (pt->pipe_wsi) {
uv_poll_stop(pt->pipe_wsi->w_read.uv.pwatcher);
uv_poll_stop(wsi_to_priv_uv(pt->pipe_wsi)->w_read.pwatcher);
lws_destroy_event_pipe(pt->pipe_wsi);
pt->pipe_wsi = NULL;
}
@ -231,8 +238,8 @@ lws_uv_close_cb_sa(uv_handle_t *handle)
for (n = 0; n < context->count_threads; n++) {
struct lws_context_per_thread *pt = &context->pt[n];
if (pt->uv.io_loop && !pt->event_loop_foreign)
uv_stop(pt->uv.io_loop);
if (pt_to_priv_uv(pt)->io_loop && !pt->event_loop_foreign)
uv_stop(pt_to_priv_uv(pt)->io_loop);
}
if (!context->pt[0].event_loop_foreign) {
@ -286,8 +293,8 @@ lws_close_all_handles_in_loop(uv_loop_t *loop)
void
lws_libuv_stop_without_kill(const struct lws_context *context, int tsi)
{
if (context->pt[tsi].uv.io_loop)
uv_stop(context->pt[tsi].uv.io_loop);
if (pt_to_priv_uv(&context->pt[tsi])->io_loop)
uv_stop(pt_to_priv_uv(&context->pt[tsi])->io_loop);
}
@ -295,8 +302,8 @@ lws_libuv_stop_without_kill(const struct lws_context *context, int tsi)
uv_loop_t *
lws_uv_getloop(struct lws_context *context, int tsi)
{
if (context->pt[tsi].uv.io_loop)
return context->pt[tsi].uv.io_loop;
if (pt_to_priv_uv(&context->pt[tsi])->io_loop)
return pt_to_priv_uv(&context->pt[tsi])->io_loop;
return NULL;
}
@ -304,7 +311,7 @@ lws_uv_getloop(struct lws_context *context, int tsi)
int
lws_libuv_check_watcher_active(struct lws *wsi)
{
uv_handle_t *h = (uv_handle_t *)wsi->w_read.uv.pwatcher;
uv_handle_t *h = (uv_handle_t *)wsi_to_priv_uv(wsi)->w_read.pwatcher;
if (!h)
return 0;
@ -321,7 +328,7 @@ elops_init_context_uv(struct lws_context *context,
context->eventlib_signal_cb = info->signal_cb;
for (n = 0; n < context->count_threads; n++)
context->pt[n].w_sigint.context = context;
pt_to_priv_uv(&context->pt[n])->w_sigint.context = context;
return 0;
}
@ -340,7 +347,7 @@ elops_destroy_context1_uv(struct lws_context *context)
if (!pt->event_loop_foreign) {
while (budget-- && (m = uv_run(pt->uv.io_loop,
while (budget-- && (m = uv_run(pt_to_priv_uv(pt)->io_loop,
UV_RUN_NOWAIT)))
;
if (m)
@ -365,15 +372,15 @@ elops_destroy_context2_uv(struct lws_context *context)
/* only for internal loops... */
if (!pt->event_loop_foreign && pt->uv.io_loop) {
if (!pt->event_loop_foreign && pt_to_priv_uv(pt)->io_loop) {
internal = 1;
if (!context->finalize_destroy_after_internal_loops_stopped)
uv_stop(pt->uv.io_loop);
uv_stop(pt_to_priv_uv(pt)->io_loop);
else {
#if UV_VERSION_MAJOR > 0
uv_loop_close(pt->uv.io_loop);
uv_loop_close(pt_to_priv_uv(pt)->io_loop);
#endif
lws_free_set_NULL(pt->uv.io_loop);
lws_free_set_NULL(pt_to_priv_uv(pt)->io_loop);
}
}
}
@ -385,14 +392,14 @@ static int
elops_wsi_logical_close_uv(struct lws *wsi)
{
if (!lws_socket_is_valid(wsi->desc.sockfd) &&
wsi->role_ops != &role_ops_raw_file)
wsi->role_ops && strcmp(wsi->role_ops->name, "raw-file"))
return 0;
if (wsi->listener || wsi->event_pipe) {
lwsl_debug("%s: %p: %d %d stop listener / pipe poll\n",
__func__, wsi, wsi->listener, wsi->event_pipe);
if (wsi->w_read.uv.pwatcher)
uv_poll_stop(wsi->w_read.uv.pwatcher);
if (wsi_to_priv_uv(wsi)->w_read.pwatcher)
uv_poll_stop(wsi_to_priv_uv(wsi)->w_read.pwatcher);
}
lwsl_debug("%s: lws_libuv_closehandle: wsi %p\n", __func__, wsi);
/*
@ -426,7 +433,7 @@ lws_libuv_closewsi_m(uv_handle_t* handle)
static void
elops_close_handle_manually_uv(struct lws *wsi)
{
uv_handle_t *h = (uv_handle_t *)wsi->w_read.uv.pwatcher;
uv_handle_t *h = (uv_handle_t *)wsi_to_priv_uv(wsi)->w_read.pwatcher;
lwsl_debug("%s: lws_libuv_closehandle: wsi %p\n", __func__, wsi);
@ -442,7 +449,7 @@ elops_close_handle_manually_uv(struct lws *wsi)
*/
wsi->desc.sockfd = LWS_SOCK_INVALID;
wsi->w_read.uv.pwatcher = NULL;
wsi_to_priv_uv(wsi)->w_read.pwatcher = NULL;
wsi->told_event_loop_closed = 1;
uv_close(h, lws_libuv_closewsi_m);
@ -452,23 +459,22 @@ static int
elops_accept_uv(struct lws *wsi)
{
struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
struct lws_io_watcher_libuv *w_read = &wsi_to_priv_uv(wsi)->w_read;
wsi->w_read.context = wsi->a.context;
w_read->context = wsi->a.context;
wsi->w_read.uv.pwatcher =
lws_malloc(sizeof(*wsi->w_read.uv.pwatcher), "uvh");
if (!wsi->w_read.uv.pwatcher)
w_read->pwatcher = lws_malloc(sizeof(*w_read->pwatcher), "uvh");
if (!w_read->pwatcher)
return -1;
if (wsi->role_ops->file_handle)
uv_poll_init(pt->uv.io_loop, wsi->w_read.uv.pwatcher,
uv_poll_init(pt_to_priv_uv(pt)->io_loop, w_read->pwatcher,
(int)(lws_intptr_t)wsi->desc.filefd);
else
uv_poll_init_socket(pt->uv.io_loop,
wsi->w_read.uv.pwatcher,
wsi->desc.sockfd);
uv_poll_init_socket(pt_to_priv_uv(pt)->io_loop,
w_read->pwatcher, wsi->desc.sockfd);
((uv_handle_t *)wsi->w_read.uv.pwatcher)->data = (void *)wsi;
((uv_handle_t *)w_read->pwatcher)->data = (void *)wsi;
return 0;
}
@ -477,14 +483,14 @@ static void
elops_io_uv(struct lws *wsi, int flags)
{
struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
struct lws_io_watcher *w = &wsi->w_read;
struct lws_io_watcher_libuv *w = &(wsi_to_priv_uv(wsi)->w_read);
int current_events = w->actual_events & (UV_READABLE | UV_WRITABLE);
lwsl_debug("%s: %p: %d\n", __func__, wsi, flags);
/* w->context is set after the loop is initialized */
if (!pt->uv.io_loop || !w->context) {
if (!pt_to_priv_uv(pt)->io_loop || !w->context) {
lwsl_info("%s: no io loop yet\n", __func__);
return;
}
@ -495,7 +501,7 @@ elops_io_uv(struct lws *wsi, int flags)
assert(0);
}
if (!w->uv.pwatcher || wsi->told_event_loop_closed) {
if (!w->pwatcher || wsi->told_event_loop_closed) {
lwsl_info("%s: no watcher\n", __func__);
return;
@ -508,7 +514,7 @@ elops_io_uv(struct lws *wsi, int flags)
if (flags & LWS_EV_READ)
current_events |= UV_READABLE;
uv_poll_start(w->uv.pwatcher, current_events, lws_io_cb);
uv_poll_start(w->pwatcher, current_events, lws_io_cb);
} else {
if (flags & LWS_EV_WRITE)
current_events &= ~UV_WRITABLE;
@ -517,10 +523,9 @@ elops_io_uv(struct lws *wsi, int flags)
current_events &= ~UV_READABLE;
if (!(current_events & (UV_READABLE | UV_WRITABLE)))
uv_poll_stop(w->uv.pwatcher);
uv_poll_stop(w->pwatcher);
else
uv_poll_start(w->uv.pwatcher, current_events,
lws_io_cb);
uv_poll_start(w->pwatcher, current_events, lws_io_cb);
}
w->actual_events = current_events;
@ -530,26 +535,26 @@ static int
elops_init_vhost_listen_wsi_uv(struct lws *wsi)
{
struct lws_context_per_thread *pt;
struct lws_io_watcher_libuv *w_read = &wsi_to_priv_uv(wsi)->w_read;
int n;
if (!wsi)
return 0;
if (wsi->w_read.context)
if (w_read->context)
return 0;
pt = &wsi->a.context->pt[(int)wsi->tsi];
if (!pt->uv.io_loop)
if (!pt_to_priv_uv(pt)->io_loop)
return 0;
wsi->w_read.context = wsi->a.context;
w_read->context = wsi->a.context;
wsi->w_read.uv.pwatcher =
lws_malloc(sizeof(*wsi->w_read.uv.pwatcher), "uvh");
if (!wsi->w_read.uv.pwatcher)
w_read->pwatcher = lws_malloc(sizeof(*w_read->pwatcher), "uvh");
if (!w_read->pwatcher)
return -1;
n = uv_poll_init_socket(pt->uv.io_loop, wsi->w_read.uv.pwatcher,
wsi->desc.sockfd);
n = uv_poll_init_socket(pt_to_priv_uv(pt)->io_loop,
w_read->pwatcher, wsi->desc.sockfd);
if (n) {
lwsl_err("uv_poll_init failed %d, sockfd=%p\n", n,
(void *)(lws_intptr_t)wsi->desc.sockfd);
@ -557,7 +562,7 @@ elops_init_vhost_listen_wsi_uv(struct lws *wsi)
return -1;
}
((uv_handle_t *)wsi->w_read.uv.pwatcher)->data = (void *)wsi;
((uv_handle_t *)w_read->pwatcher)->data = (void *)wsi;
elops_io_uv(wsi, LWS_EV_START | LWS_EV_READ);
@ -567,8 +572,8 @@ elops_init_vhost_listen_wsi_uv(struct lws *wsi)
static void
elops_run_pt_uv(struct lws_context *context, int tsi)
{
if (context->pt[tsi].uv.io_loop)
uv_run(context->pt[tsi].uv.io_loop, 0);
if (pt_to_priv_uv(&context->pt[tsi])->io_loop)
uv_run(pt_to_priv_uv(&context->pt[tsi])->io_loop, 0);
}
static void
@ -582,7 +587,7 @@ elops_destroy_pt_uv(struct lws_context *context, int tsi)
if (!lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV))
return;
if (!pt->uv.io_loop)
if (!pt_to_priv_uv(pt)->io_loop)
return;
if (pt->event_loop_destroy_processing_done)
@ -591,7 +596,7 @@ elops_destroy_pt_uv(struct lws_context *context, int tsi)
pt->event_loop_destroy_processing_done = 1;
if (!pt->event_loop_foreign) {
uv_signal_stop(&pt->w_sigint.uv.watcher);
uv_signal_stop(&pt_to_priv_uv(pt)->w_sigint.watcher);
ns = LWS_ARRAY_SIZE(sigs);
if (lws_check_opt(context->options,
@ -599,18 +604,18 @@ elops_destroy_pt_uv(struct lws_context *context, int tsi)
ns = 2;
for (m = 0; m < ns; m++) {
uv_signal_stop(&pt->uv.signals[m]);
uv_close((uv_handle_t *)&pt->uv.signals[m],
uv_signal_stop(&pt_to_priv_uv(pt)->signals[m]);
uv_close((uv_handle_t *)&pt_to_priv_uv(pt)->signals[m],
lws_uv_close_cb_sa);
}
} else
lwsl_debug("%s: not closing pt signals\n", __func__);
uv_timer_stop(&pt->uv.sultimer);
uv_close((uv_handle_t *)&pt->uv.sultimer, lws_uv_close_cb_sa);
uv_timer_stop(&pt_to_priv_uv(pt)->sultimer);
uv_close((uv_handle_t *)&pt_to_priv_uv(pt)->sultimer, lws_uv_close_cb_sa);
uv_idle_stop(&pt->uv.idle);
uv_close((uv_handle_t *)&pt->uv.idle, lws_uv_close_cb_sa);
uv_idle_stop(&pt_to_priv_uv(pt)->idle);
uv_close((uv_handle_t *)&pt_to_priv_uv(pt)->idle, lws_uv_close_cb_sa);
}
/*
@ -624,11 +629,12 @@ int
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;
if (!pt->uv.io_loop) {
if (!ptpriv->io_loop) {
if (!loop) {
loop = lws_malloc(sizeof(*loop), "libuv loop");
if (!loop) {
@ -647,9 +653,9 @@ elops_init_pt_uv(struct lws_context *context, void *_loop, int tsi)
pt->event_loop_foreign = 1;
}
pt->uv.io_loop = loop;
uv_idle_init(loop, &pt->uv.idle);
LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&pt->uv.idle, context);
ptpriv->io_loop = loop;
uv_idle_init(loop, &ptpriv->idle);
LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&ptpriv->idle, context);
ns = LWS_ARRAY_SIZE(sigs);
@ -658,13 +664,13 @@ elops_init_pt_uv(struct lws_context *context, void *_loop, int tsi)
ns = 2;
if (!pt->event_loop_foreign) {
assert(ns <= (int)LWS_ARRAY_SIZE(pt->uv.signals));
assert(ns <= (int)LWS_ARRAY_SIZE(ptpriv->signals));
for (n = 0; n < ns; n++) {
uv_signal_init(loop, &pt->uv.signals[n]);
LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&pt->uv.signals[n],
uv_signal_init(loop, &ptpriv->signals[n]);
LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&ptpriv->signals[n],
context);
pt->uv.signals[n].data = pt->context;
uv_signal_start(&pt->uv.signals[n],
ptpriv->signals[n].data = pt->context;
uv_signal_start(&ptpriv->signals[n],
lws_uv_signal_handler, sigs[n]);
}
}
@ -687,8 +693,8 @@ elops_init_pt_uv(struct lws_context *context, void *_loop, int tsi)
if (!first)
return status;
uv_timer_init(pt->uv.io_loop, &pt->uv.sultimer);
LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&pt->uv.sultimer, context);
uv_timer_init(ptpriv->io_loop, &ptpriv->sultimer);
LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&ptpriv->sultimer, context);
return status;
}
@ -710,7 +716,8 @@ lws_libuv_closewsi(uv_handle_t* handle)
*/
#if defined(LWS_WITH_SERVER)
if (wsi->role_ops == &role_ops_listen && wsi->a.context->deprecated) {
if (wsi->role_ops && !strcmp(wsi->role_ops->name, "listen") &&
wsi->a.context->deprecated) {
lspd = 1;
context->deprecation_pending_listen_close_count--;
if (!context->deprecation_pending_listen_close_count)
@ -773,8 +780,9 @@ void
lws_libuv_closehandle(struct lws *wsi)
{
uv_handle_t* handle;
struct lws_io_watcher_libuv *w_read = &wsi_to_priv_uv(wsi)->w_read;
if (!wsi->w_read.uv.pwatcher)
if (!w_read->pwatcher)
return;
if (wsi->told_event_loop_closed) {
@ -791,16 +799,16 @@ lws_libuv_closehandle(struct lws *wsi)
* handle->data.
*/
handle = (uv_handle_t *)wsi->w_read.uv.pwatcher;
handle = (uv_handle_t *)w_read->pwatcher;
/* ensure we can only do this once */
wsi->w_read.uv.pwatcher = NULL;
w_read->pwatcher = NULL;
uv_close(handle, lws_libuv_closewsi);
}
struct lws_event_loop_ops event_loop_ops_uv = {
static const struct lws_event_loop_ops event_loop_ops_uv = {
/* name */ "libuv",
/* init_context */ elops_init_context_uv,
/* destroy_context1 */ elops_destroy_context1_uv,
@ -817,4 +825,23 @@ struct lws_event_loop_ops event_loop_ops_uv = {
/* destroy wsi */ NULL,
/* flags */ 0,
/* evlib_size_ctx */ sizeof(struct lws_context_eventlibs_libuv),
/* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_libuv),
/* evlib_size_vh */ 0,
/* evlib_size_wsi */ sizeof(struct lws_io_watcher_libuv),
};
#if defined(LWS_WITH_EVLIB_PLUGINS)
LWS_VISIBLE
#endif
const lws_plugin_evlib_t evlib_uv = {
.hdr = {
"libuv event loop",
"lws_evlib_plugin",
LWS_PLUGIN_API_MAGIC
},
.ops = &event_loop_ops_uv
};

View file

@ -46,11 +46,17 @@
(--(LWS_UV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x)-> \
count_event_loop_static_asset_handles))
struct lws_signal_watcher_libuv {
uv_signal_t watcher;
struct lws_context *context;
};
struct lws_pt_eventlibs_libuv {
uv_loop_t *io_loop;
uv_signal_t signals[8];
uv_timer_t sultimer;
uv_idle_t idle;
struct lws_signal_watcher_libuv w_sigint;
};
struct lws_context_eventlibs_libuv {
@ -59,14 +65,14 @@ struct lws_context_eventlibs_libuv {
struct lws_io_watcher_libuv {
uv_poll_t *pwatcher;
struct lws_context *context;
uint8_t actual_events;
};
struct lws_signal_watcher_libuv {
uv_signal_t watcher;
struct lws_wsi_eventlibs_libuv {
struct lws_io_watcher_libuv w_read;
};
extern struct lws_event_loop_ops event_loop_ops_uv;
uv_loop_t *
lws_uv_getloop(struct lws_context *context, int tsi);

View file

@ -19,12 +19,11 @@
* 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.
*
* This is included from private-lib-core.h if LWS_ROLE_WS
* IN THE SOFTWARE
*/
#include <private-lib-core.h>
#include "private-lib-event-libs-poll.h"
struct lws_event_loop_ops event_loop_ops_poll = {
/* name */ "poll",
@ -43,4 +42,19 @@ struct lws_event_loop_ops event_loop_ops_poll = {
/* destroy wsi */ NULL,
/* flags */ LELOF_ISPOLL,
/* evlib_size_ctx */ 0,
/* evlib_size_pt */ 0,
/* evlib_size_vh */ 0,
/* evlib_size_wsi */ 0,
};
const lws_plugin_evlib_t evlib_poll = {
.hdr = {
"poll",
"lws_evlib_plugin",
LWS_PLUGIN_API_MAGIC
},
.ops = &event_loop_ops_poll
};

View file

@ -60,27 +60,9 @@ struct lws_event_loop_ops {
void (*destroy_wsi)(struct lws *wsi);
uint8_t flags;
uint16_t evlib_size_ctx;
uint16_t evlib_size_pt;
uint16_t evlib_size_vh;
uint16_t evlib_size_wsi;
};
/* bring in event libs private declarations */
#if defined(LWS_WITH_POLL)
#include "private-lib-event-libs-poll.h"
#endif
#if defined(LWS_WITH_LIBUV)
#include "private-lib-event-libs-libuv.h"
#endif
#if defined(LWS_WITH_LIBEVENT)
#include "private-lib-event-libs-libevent.h"
#endif
#if defined(LWS_WITH_GLIB)
#include "private-lib-event-libs-glib.h"
#endif
#if defined(LWS_WITH_LIBEV)
#include "private-lib-event-libs-libev.h"
#endif

View file

@ -50,7 +50,7 @@
#endif
#endif /* win32 */
#define COMBO_SIZEOF 256
#define COMBO_SIZEOF 512
#if !defined(LWS_PLAT_FREERTOS)
@ -189,7 +189,7 @@ lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb)
}
#endif
if (cb(dirpath, user, &lde)) {
while (i++ < n)
while (++i < n)
free(namelist[i]);
goto bail;
}
@ -265,7 +265,16 @@ lws_dir_rm_rf_cb(const char *dirpath, void *user, struct lws_dir_entry *lde)
lws_snprintf(path, sizeof(path), "%s%c%s", dirpath, csep, lde->name);
if (lde->type == LDOT_DIR) {
lws_dir(path, NULL, lws_dir_rm_rf_cb);
#if !defined(WIN32) && !defined(_WIN32)
char dummy[8];
/*
* hm... eg, recursive dir symlinks can show up a LDOT_DIR
* here
*/
if (readlink(path, dummy, sizeof(dummy)) < 0)
#endif
lws_dir(path, NULL, lws_dir_rm_rf_cb);
if (rmdir(path))
lwsl_warn("%s: rmdir %s failed %d\n", __func__, path, errno);
} else {
@ -287,7 +296,8 @@ lws_dir_rm_rf_cb(const char *dirpath, void *user, struct lws_dir_entry *lde)
#endif
#if defined(LWS_WITH_PLUGINS)
#if defined(LWS_WITH_PLUGINS) || \
(defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS))
struct lws_plugins_args {
struct lws_plugin **pplugin;
@ -301,19 +311,38 @@ static int
lws_plugins_dir_cb(const char *dirpath, void *user, struct lws_dir_entry *lde)
{
struct lws_plugins_args *pa = (struct lws_plugins_args *)user;
char path[256];
char path[256], base[64], *q = base;
const char *p;
if (strlen(lde->name) < 7)
return 0;
/* if he's given a filter, only match if name + 3 matches it */
if (pa->filter && strncmp(lde->name + 3, pa->filter, strlen(pa->filter)))
/*
* The actual plugin names for protocol plugins look like
* "libprotocol_lws_ssh_base.so" and for event libs
* "libwebsockets-evlib_ev.so"... to recover the base name of
* "lws_ssh_base" and "evlib_ev" we strip from the left to after the
* first _ or -, and then truncate at the first .
*/
p = lde->name;
while (*p && *p != '_' && *p != '-')
p++;
if (!*p)
return 0;
p++;
while (*p && *p != '.' && lws_ptr_diff(q, base) < (int)sizeof(base) - 1)
*q++ = *p++;
*q = '\0';
/* if he's given a filter, only match if base matches it */
if (pa->filter && strcmp(base, pa->filter))
return 0;
lws_snprintf(path, sizeof(path) - 1, "%s/%s", dirpath, lde->name);
lwsl_notice(" %s\n", path);
return !lws_plat_dlopen(pa->pplugin, path, lde->name + 3, pa->_class,
return !lws_plat_dlopen(pa->pplugin, path, base, pa->_class,
pa->each, pa->each_user);
}

View file

@ -65,7 +65,7 @@ if (LWS_WITH_NETWORK)
endif()
endif()
if (LWS_WITH_PLUGINS AND LWS_WITH_LIBUV)
if (LWS_WITH_PLUGINS OR LWS_WITH_EVLIB_PLUGINS)
list(APPEND SOURCES plat/unix/unix-plugins.c)
endif()

View file

@ -80,6 +80,7 @@ lws_sul_plat_unix(lws_sorted_usec_list_t *sul)
}
#endif
#if defined(LWS_WITH_PLUGINS)
static int
protocol_plugin_cb(struct lws_plugin *pin, void *each_user)
{
@ -92,6 +93,7 @@ protocol_plugin_cb(struct lws_plugin *pin, void *each_user)
return 0;
}
#endif
int
lws_plat_init(struct lws_context *context,

View file

@ -1,7 +1,7 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@ -27,15 +27,17 @@
#endif
#include "private-lib-core.h"
int
lws_plat_pipe_create(struct lws *wsi)
{
struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
#if defined(LWS_HAVE_EVENTFD)
pt->dummy_pipe_fds[0] = eventfd(0, EFD_CLOEXEC|EFD_NONBLOCK);
pt->dummy_pipe_fds[0] = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
pt->dummy_pipe_fds[1] = -1;
return pt->dummy_pipe_fds[0]<0?-1:0;
return pt->dummy_pipe_fds[0] < 0 ? -1 : 0;
#elif defined(LWS_HAVE_PIPE2)
return pipe2(pt->dummy_pipe_fds, O_NONBLOCK);
#else
@ -49,6 +51,7 @@ lws_plat_pipe_signal(struct lws *wsi)
struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
#if defined(LWS_HAVE_EVENTFD)
eventfd_t value = 1;
return eventfd_write(pt->dummy_pipe_fds[0], value);
#else
char buf = 0;

View file

@ -30,10 +30,9 @@
#include <pwd.h>
#include <grp.h>
#ifdef LWS_WITH_PLUGINS
#if defined(LWS_WITH_PLUGINS) || defined(LWS_WITH_EVLIB_PLUGINS)
#include <dlfcn.h>
#endif
#include <dirent.h>
const lws_plugin_header_t *
lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath,

View file

@ -55,6 +55,7 @@ lws_plat_context_early_init(void)
return 1;
}
#if defined(LWS_WITH_PLUGINS)
static int
protocol_plugin_cb(struct lws_plugin *pin, void *each_user)
{
@ -67,6 +68,7 @@ protocol_plugin_cb(struct lws_plugin *pin, void *each_user)
return 0;
}
#endif
int
lws_plat_init(struct lws_context *context,

View file

@ -27,7 +27,8 @@
#endif
#include "private-lib-core.h"
#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0)
#if (defined(LWS_WITH_PLUGINS) || defined(LWS_WITH_EVLIB_PLUGINS)) && \
(UV_VERSION_MAJOR > 0)
const lws_plugin_header_t *
lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath,
@ -116,11 +117,13 @@ protocol_plugin_cb(struct lws_plugin *pin, void *each_user)
return 0;
}
#endif
int
lws_plat_plugins_init(struct lws_context *context, const char * const *d)
{
#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0)
#if (defined(LWS_WITH_PLUGINS) || defined(LWS_WITH_EVLIB_PLUGINS)) && \
(UV_VERSION_MAJOR > 0)
if (info->plugin_dirs) {
uv_loop_init(&context->uv.loop);
lws_plugins_init(&context->plugin_list, info->plugin_dirs,
@ -135,7 +138,8 @@ lws_plat_plugins_init(struct lws_context *context, const char * const *d)
int
lws_plat_plugins_destroy(struct lws_context * context)
{
#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0)
#if (defined(LWS_WITH_PLUGINS) || defined(LWS_WITH_EVLIB_PLUGINS)) && \
(UV_VERSION_MAJOR > 0)
if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV) &&
context->plugin_list) {
lws_plugins_destroy(&context->plugin_list, NULL, NULL);

View file

@ -66,6 +66,7 @@ lws_create_basic_wsi(struct lws_context *context, int tsi,
const struct lws_role_ops *ops)
{
struct lws *new_wsi;
size_t s = sizeof(*new_wsi);
if (!context->vhost_list)
return NULL;
@ -76,12 +77,20 @@ lws_create_basic_wsi(struct lws_context *context, int tsi,
return NULL;
}
new_wsi = lws_zalloc(sizeof(*new_wsi), "new wsi");
#if defined(LWS_WITH_EVENT_LIBS)
s += vhost->context->event_loop_ops->evlib_size_wsi;
#endif
new_wsi = lws_zalloc(s, "new wsi");
if (new_wsi == NULL) {
lwsl_err("Out of memory for new connection\n");
return NULL;
}
#if defined(LWS_WITH_EVENT_LIBS)
new_wsi->evlib_wsi = (uint8_t *)new_wsi + sizeof(*new_wsi);
#endif
new_wsi->tsi = tsi;
new_wsi->a.context = context;
new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
@ -324,7 +333,7 @@ windows_pipe_poll_hack(lws_sorted_usec_list_t *sul)
*/
} else
if (br)
wsi1->protocol->callback(wsi1,
wsi1->a.protocol->callback(wsi1,
LWS_CALLBACK_RAW_RX_FILE,
NULL, NULL, 0);
}
@ -417,8 +426,8 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i)
}
lsp->stdwsi[n]->lsp_channel = n;
lws_vhost_bind_wsi(i->vh, lsp->stdwsi[n]);
lsp->stdwsi[n]->protocol = pcol;
lsp->stdwsi[n]->opaque_user_data = i->opaque;
lsp->stdwsi[n]->a.protocol = pcol;
lsp->stdwsi[n]->a.opaque_user_data = i->opaque;
lsp->stdwsi[n]->desc.filefd = lsp->pipe_fds[n][!n];
lsp->stdwsi[n]->file_desc = 1;

View file

@ -48,6 +48,7 @@
static struct lws *
__lws_shadow_wsi(struct lws_dbus_ctx *ctx, DBusWatch *w, int fd, int create_ok)
{
size_t s = sizeof(struct lws);
struct lws *wsi;
if (fd < 0 || fd >= (int)ctx->vh->context->fd_limit_per_thread) {
@ -68,12 +69,20 @@ __lws_shadow_wsi(struct lws_dbus_ctx *ctx, DBusWatch *w, int fd, int create_ok)
if (!create_ok)
return NULL;
wsi = lws_zalloc(sizeof(*wsi), "shadow wsi");
#if defined(LWS_WITH_EVENT_LIBS)
s += ctx->vh->context->event_loop_ops->evlib_size_wsi;
#endif
wsi = lws_zalloc(s, "shadow wsi");
if (wsi == NULL) {
lwsl_err("Out of mem\n");
return NULL;
}
#if defined(LWS_WITH_EVENT_LIBS)
wsi->evlib_wsi = (uint8_t *)wsi + sizeof(*wsi);
#endif
lwsl_info("%s: creating shadow wsi\n", __func__);
wsi->a.context = ctx->vh->context;

View file

@ -271,10 +271,21 @@ done_list:
goto deal;
}
wsi = lws_zalloc(sizeof(struct lws), "listen wsi");
if (wsi == NULL) {
lwsl_err("Out of mem\n");
goto bail;
{
size_t s = sizeof(struct lws);
#if defined(LWS_WITH_EVENT_LIBS)
s += vhost->context->event_loop_ops->evlib_size_wsi;
#endif
wsi = lws_zalloc(s, "listen wsi");
if (wsi == NULL) {
lwsl_err("Out of mem\n");
goto bail;
}
#if defined(LWS_WITH_EVENT_LIBS)
wsi->evlib_wsi = (uint8_t *)wsi + sizeof(*wsi);
#endif
}
#ifdef LWS_WITH_UNIX_SOCK

View file

@ -30,8 +30,14 @@ rops_handle_POLLIN_pipe(struct lws_context_per_thread *pt, struct lws *wsi,
{
#if defined(LWS_HAVE_EVENTFD)
eventfd_t value;
if (eventfd_read(wsi->desc.sockfd, &value) < 0)
int n;
n = eventfd_read(wsi->desc.sockfd, &value);
if (n < 0) {
lwsl_notice("%s: eventfd read %d bailed errno %d\n", __func__,
wsi->desc.sockfd, LWS_ERRNO);
return LWS_HPI_RET_PLEASE_CLOSE_ME;
}
#elif !defined(WIN32) && !defined(_WIN32)
char s[100];
int n;

View file

@ -780,7 +780,7 @@ done:
lws_struct_json_init_parse(&ctx, NULL, &a);
m = lejp_parse(&ctx, (uint8_t *)jig_conf, strlen(jig_conf));
m = lejp_parse(&ctx, (uint8_t *)jig_conf, (int)strlen(jig_conf));
if (m < 0 || !a.dest) {
lwsl_err("%s: line %d: JSON decode failed '%s'\n",

View file

@ -28,6 +28,7 @@ if (LWS_WITH_LIBUV)
message("libuv libraries: ${LIBUV_LIBRARIES}")
include_directories("${LIBUV_INCLUDE_DIRS}")
set(extralibs ${extralibs} ${LIBUV_LIBRARIES})
list(APPEND SRCS libuv.c)
endif()
if (LWS_WITH_LIBEVENT)
find_path(LIBEVENT_INCLUDE_DIRS NAMES event2/event.h)
@ -36,6 +37,7 @@ if (LWS_WITH_LIBEVENT)
message("libevent libraries: ${LIBEVENT_LIBRARIES}")
include_directories("${LIBEVENT_INCLUDE_DIRS}")
set(extralibs ${extralibs} ${LIBEVENT_LIBRARIES})
list(APPEND SRCS libevent.c)
endif()
if (LWS_WITH_LIBEV)
find_path(LIBEV_INCLUDE_DIRS NAMES ev.h)
@ -44,6 +46,7 @@ if (LWS_WITH_LIBEV)
message("libev libraries: ${LIBEV_LIBRARIES}")
include_directories("${LIBEV_INCLUDE_DIRS}")
set(extralibs ${extralibs} ${LIBEV_LIBRARIES})
list(APPEND SRCS libev.c)
endif()
if (LWS_WITH_GLIB)
set(LWS_GLIB_INCLUDE_DIRS CACHE PATH "Path to the glib include directory")
@ -67,6 +70,7 @@ if (LWS_WITH_GLIB)
message("glib libraries: ${GLIB_LIBRARIES}")
include_directories("${GLIB_INCLUDE_DIRS}")
set(extralibs ${extralibs} ${GLIB_LIBRARIES})
list(APPEND SRCS glib.c)
endif()
message("Extra libs: ${extralibs}")

View file

@ -0,0 +1,92 @@
/*
* lws-minimal-http-server-eventlib-foreign
*
* Written in 2010-2020 by Andy Green <andy@warmcat.com>
*
* This file is made available under the Creative Commons CC0 1.0
* Universal Public Domain Dedication.
*
* The glib specific code
*/
#include <libwebsockets.h>
#include <string.h>
#include <signal.h>
#include <glib-2.0/glib.h>
#include <glib-unix.h>
#include "private.h"
typedef struct lws_glib_tag {
GSource *gs;
guint tag;
} lws_glib_tag_t;
#define lws_gs_valid(t) (t.gs)
#define lws_gs_destroy(t) if (lws_gs_valid(t)) { \
g_source_remove(t.tag); \
g_source_unref(t.gs); \
t.gs = NULL; t.tag = 0; }
static GMainLoop *loop_glib;
static lws_glib_tag_t timer_outer_glib, sighandler_glib;
static int
timer_cb_glib(void *p)
{
foreign_timer_service(loop_glib);
return 1;
}
static void
signal_cb_glib(void *p)
{
signal_cb(SIGINT);
}
static void
foreign_event_loop_init_and_run_glib(void)
{
/* we create and start our "foreign loop" */
loop_glib = g_main_loop_new(NULL, 0);
sighandler_glib.gs = g_unix_signal_source_new(SIGINT);
g_source_set_callback(sighandler_glib.gs, G_SOURCE_FUNC(signal_cb_glib),
NULL, NULL);
sighandler_glib.tag = g_source_attach(sighandler_glib.gs,
g_main_loop_get_context(loop_glib));
timer_outer_glib.gs = g_timeout_source_new(1000);
g_source_set_callback(timer_outer_glib.gs, timer_cb_glib, NULL, NULL);
timer_outer_glib.tag = g_source_attach(timer_outer_glib.gs,
g_main_loop_get_context(loop_glib));
g_main_loop_run(loop_glib);
}
static void
foreign_event_loop_stop_glib(void)
{
g_main_loop_quit(loop_glib);
}
static void
foreign_event_loop_cleanup_glib(void)
{
/* cleanup the foreign loop assets */
lws_gs_destroy(sighandler_glib);
lws_gs_destroy(timer_outer_glib);
g_main_loop_unref(loop_glib);
loop_glib = NULL;
}
const struct ops ops_glib = {
foreign_event_loop_init_and_run_glib,
foreign_event_loop_stop_glib,
foreign_event_loop_cleanup_glib
};

View file

@ -0,0 +1,76 @@
/*
* lws-minimal-http-server-eventlib-foreign
*
* Written in 2010-2020 by Andy Green <andy@warmcat.com>
*
* This file is made available under the Creative Commons CC0 1.0
* Universal Public Domain Dedication.
*
* The libev specific code
*/
#include <libwebsockets.h>
#include <ev.h>
#include <string.h>
#include <signal.h>
#include "private.h"
static struct ev_loop *loop_ev;
static struct ev_timer timer_outer_ev;
static struct ev_signal sighandler_ev;
static void
timer_cb_ev(struct ev_loop *loop, struct ev_timer *watcher, int revents)
{
foreign_timer_service(loop_ev);
}
static void
signal_cb_ev(struct ev_loop *loop, struct ev_signal *watcher, int revents)
{
signal_cb(watcher->signum);
}
static void
foreign_event_loop_init_and_run_libev(void)
{
/* we create and start our "foreign loop" */
loop_ev = ev_loop_new(0);
ev_signal_init(&sighandler_ev, signal_cb_ev, SIGINT);
ev_signal_start(loop_ev, &sighandler_ev);
ev_timer_init(&timer_outer_ev, timer_cb_ev, 0, 1);
ev_timer_start(loop_ev, &timer_outer_ev);
ev_run(loop_ev, 0);
}
static void
foreign_event_loop_stop_libev(void)
{
ev_break(loop_ev, EVBREAK_ALL);
}
static void
foreign_event_loop_cleanup_libev(void)
{
/* cleanup the foreign loop assets */
ev_timer_stop(loop_ev, &timer_outer_ev);
ev_signal_stop(loop_ev, &sighandler_ev);
ev_run(loop_ev, 0);
ev_loop_destroy(loop_ev);
}
const struct ops ops_libev = {
foreign_event_loop_init_and_run_libev,
foreign_event_loop_stop_libev,
foreign_event_loop_cleanup_libev
};

View file

@ -0,0 +1,84 @@
/*
* lws-minimal-http-server-eventlib-foreign
*
* Written in 2010-2020 by Andy Green <andy@warmcat.com>
*
* This file is made available under the Creative Commons CC0 1.0
* Universal Public Domain Dedication.
*
* The libevent specific code
*/
#include <libwebsockets.h>
#include <event2/event.h>
#include <string.h>
#include <signal.h>
#include "private.h"
static struct event_base *loop_event;
static struct event *timer_outer_event;
static struct event *sighandler_event;
static void
timer_cb_event(int fd, short event, void *arg)
{
foreign_timer_service(loop_event);
}
static void
signal_cb_event(int fd, short event, void *arg)
{
signal_cb((int)(lws_intptr_t)arg);
}
static void
foreign_event_loop_init_and_run_libevent(void)
{
struct timeval tv;
/* we create and start our "foreign loop" */
tv.tv_sec = 1;
tv.tv_usec = 0;
loop_event = event_base_new();
sighandler_event = evsignal_new(loop_event, SIGINT, signal_cb_event,
(void*)SIGINT);
timer_outer_event = event_new(loop_event, -1, EV_PERSIST,
timer_cb_event, NULL);
//evtimer_new(loop_event, timer_cb_event, NULL);
evtimer_add(timer_outer_event, &tv);
event_base_loop(loop_event, 0);
}
static void
foreign_event_loop_stop_libevent(void)
{
event_base_loopexit(loop_event, NULL);
}
static void
foreign_event_loop_cleanup_libevent(void)
{
/* cleanup the foreign loop assets */
evtimer_del(timer_outer_event);
event_free(timer_outer_event);
evsignal_del(sighandler_event);
event_free(sighandler_event);
event_base_loop(loop_event, 0);
event_base_free(loop_event);
}
const struct ops ops_libevent = {
foreign_event_loop_init_and_run_libevent,
foreign_event_loop_stop_libevent,
foreign_event_loop_cleanup_libevent
};

View file

@ -0,0 +1,91 @@
/*
* lws-minimal-http-server-eventlib-foreign
*
* Written in 2010-2020 by Andy Green <andy@warmcat.com>
*
* This file is made available under the Creative Commons CC0 1.0
* Universal Public Domain Dedication.
*
* The libuv specific code
*/
#include <libwebsockets.h>
#include <string.h>
#include <signal.h>
#include <uv.h>
#ifdef LWS_HAVE_UV_VERSION_H
#include <uv-version.h>
#endif
#ifdef LWS_HAVE_NEW_UV_VERSION_H
#include <uv/version.h>
#endif
#include "private.h"
static uv_loop_t loop_uv;
static uv_timer_t timer_outer_uv;
static uv_signal_t sighandler_uv;
static void
timer_cb_uv(uv_timer_t *t)
{
foreign_timer_service(&loop_uv);
}
static void
signal_cb_uv(uv_signal_t *watcher, int signum)
{
signal_cb(signum);
}
static void
foreign_event_loop_init_and_run_libuv(void)
{
/* we create and start our "foreign loop" */
#if (UV_VERSION_MAJOR > 0) // Travis...
uv_loop_init(&loop_uv);
#endif
uv_signal_init(&loop_uv, &sighandler_uv);
uv_signal_start(&sighandler_uv, signal_cb_uv, SIGINT);
uv_timer_init(&loop_uv, &timer_outer_uv);
#if (UV_VERSION_MAJOR > 0) // Travis...
uv_timer_start(&timer_outer_uv, timer_cb_uv, 0, 1000);
#else
(void)timer_cb_uv;
#endif
uv_run(&loop_uv, UV_RUN_DEFAULT);
}
static void
foreign_event_loop_stop_libuv(void)
{
uv_stop(&loop_uv);
}
static void
foreign_event_loop_cleanup_libuv(void)
{
/* cleanup the foreign loop assets */
uv_timer_stop(&timer_outer_uv);
uv_close((uv_handle_t*)&timer_outer_uv, NULL);
uv_signal_stop(&sighandler_uv);
uv_close((uv_handle_t *)&sighandler_uv, NULL);
uv_run(&loop_uv, UV_RUN_DEFAULT);
#if (UV_VERSION_MAJOR > 0) // Travis...
uv_loop_close(&loop_uv);
#endif
}
const struct ops ops_libuv = {
foreign_event_loop_init_and_run_libuv,
foreign_event_loop_stop_libuv,
foreign_event_loop_cleanup_libuv
};

View file

@ -23,11 +23,12 @@
#include <string.h>
#include <signal.h>
struct lws_context_creation_info info;
static struct lws_context *context;
static int lifetime = 5, reported;
#include "private.h"
static void foreign_timer_service(void *foreign_loop);
static struct lws_context_creation_info info;
static const struct ops *ops = NULL;
struct lws_context *context;
int lifetime = 5, reported;
enum {
TEST_STATE_CREATE_LWS_CONTEXT,
@ -57,7 +58,7 @@ static const struct lws_http_mount mount = {
/* .basic_auth_login_file */ NULL,
};
static void
void
signal_cb(int signum)
{
lwsl_notice("Signal %d caught, exiting...\n", signum);
@ -73,268 +74,9 @@ signal_cb(int signum)
lws_context_destroy(context);
}
/*
* The event-loop specific foreign loop code, one set for each event loop lib
*
* Only the code in this section is specific to the event library used.
*/
#if defined(LWS_WITH_LIBUV)
static uv_loop_t loop_uv;
static uv_timer_t timer_outer_uv;
static uv_signal_t sighandler_uv;
static void
timer_cb_uv(uv_timer_t *t)
{
foreign_timer_service(&loop_uv);
}
static void
signal_cb_uv(uv_signal_t *watcher, int signum)
{
signal_cb(signum);
}
static void
foreign_event_loop_init_and_run_libuv(void)
{
/* we create and start our "foreign loop" */
#if (UV_VERSION_MAJOR > 0) // Travis...
uv_loop_init(&loop_uv);
#endif
uv_signal_init(&loop_uv, &sighandler_uv);
uv_signal_start(&sighandler_uv, signal_cb_uv, SIGINT);
uv_timer_init(&loop_uv, &timer_outer_uv);
#if (UV_VERSION_MAJOR > 0) // Travis...
uv_timer_start(&timer_outer_uv, timer_cb_uv, 0, 1000);
#else
(void)timer_cb_uv;
#endif
uv_run(&loop_uv, UV_RUN_DEFAULT);
}
static void
foreign_event_loop_stop_libuv(void)
{
uv_stop(&loop_uv);
}
static void
foreign_event_loop_cleanup_libuv(void)
{
/* cleanup the foreign loop assets */
uv_timer_stop(&timer_outer_uv);
uv_close((uv_handle_t*)&timer_outer_uv, NULL);
uv_signal_stop(&sighandler_uv);
uv_close((uv_handle_t *)&sighandler_uv, NULL);
uv_run(&loop_uv, UV_RUN_DEFAULT);
#if (UV_VERSION_MAJOR > 0) // Travis...
uv_loop_close(&loop_uv);
#endif
}
#endif
#if defined(LWS_WITH_LIBEVENT)
static struct event_base *loop_event;
static struct event *timer_outer_event;
static struct event *sighandler_event;
static void
timer_cb_event(int fd, short event, void *arg)
{
foreign_timer_service(loop_event);
}
static void
signal_cb_event(int fd, short event, void *arg)
{
signal_cb((int)(lws_intptr_t)arg);
}
static void
foreign_event_loop_init_and_run_libevent(void)
{
struct timeval tv;
/* we create and start our "foreign loop" */
tv.tv_sec = 1;
tv.tv_usec = 0;
loop_event = event_base_new();
sighandler_event = evsignal_new(loop_event, SIGINT, signal_cb_event,
(void*)SIGINT);
timer_outer_event = event_new(loop_event, -1, EV_PERSIST,
timer_cb_event, NULL);
//evtimer_new(loop_event, timer_cb_event, NULL);
evtimer_add(timer_outer_event, &tv);
event_base_loop(loop_event, 0);
}
static void
foreign_event_loop_stop_libevent(void)
{
event_base_loopexit(loop_event, NULL);
}
static void
foreign_event_loop_cleanup_libevent(void)
{
/* cleanup the foreign loop assets */
evtimer_del(timer_outer_event);
event_free(timer_outer_event);
evsignal_del(sighandler_event);
event_free(sighandler_event);
event_base_loop(loop_event, 0);
event_base_free(loop_event);
}
#endif
#if defined(LWS_WITH_GLIB)
#include <glib-2.0/glib.h>
#include <glib-unix.h>
typedef struct lws_glib_tag {
GSource *gs;
guint tag;
} lws_glib_tag_t;
#define lws_gs_valid(t) (t.gs)
#define lws_gs_destroy(t) if (lws_gs_valid(t)) { \
g_source_remove(t.tag); \
g_source_unref(t.gs); \
t.gs = NULL; t.tag = 0; }
static GMainLoop *loop_glib;
static lws_glib_tag_t timer_outer_glib, sighandler_glib;
static int
timer_cb_glib(void *p)
{
foreign_timer_service(loop_glib);
return 1;
}
static void
signal_cb_glib(void *p)
{
signal_cb(SIGINT);
}
static void
foreign_event_loop_init_and_run_glib(void)
{
/* we create and start our "foreign loop" */
loop_glib = g_main_loop_new(NULL, 0);
sighandler_glib.gs = g_unix_signal_source_new(SIGINT);
g_source_set_callback(sighandler_glib.gs, G_SOURCE_FUNC(signal_cb_glib),
NULL, NULL);
sighandler_glib.tag = g_source_attach(sighandler_glib.gs,
g_main_loop_get_context(loop_glib));
timer_outer_glib.gs = g_timeout_source_new(1000);
g_source_set_callback(timer_outer_glib.gs, timer_cb_glib, NULL, NULL);
timer_outer_glib.tag = g_source_attach(timer_outer_glib.gs,
g_main_loop_get_context(loop_glib));
g_main_loop_run(loop_glib);
}
static void
foreign_event_loop_stop_glib(void)
{
g_main_loop_quit(loop_glib);
}
static void
foreign_event_loop_cleanup_glib(void)
{
/* cleanup the foreign loop assets */
lws_gs_destroy(sighandler_glib);
lws_gs_destroy(timer_outer_glib);
g_main_loop_unref(loop_glib);
loop_glib = NULL;
}
#endif
#if defined(LWS_WITH_LIBEV)
static struct ev_loop *loop_ev;
static struct ev_timer timer_outer_ev;
static struct ev_signal sighandler_ev;
static void
timer_cb_ev(struct ev_loop *loop, struct ev_timer *watcher, int revents)
{
foreign_timer_service(loop_ev);
}
static void
signal_cb_ev(struct ev_loop *loop, struct ev_signal *watcher, int revents)
{
signal_cb(watcher->signum);
}
static void
foreign_event_loop_init_and_run_libev(void)
{
/* we create and start our "foreign loop" */
loop_ev = ev_loop_new(0);
ev_signal_init(&sighandler_ev, signal_cb_ev, SIGINT);
ev_signal_start(loop_ev, &sighandler_ev);
ev_timer_init(&timer_outer_ev, timer_cb_ev, 0, 1);
ev_timer_start(loop_ev, &timer_outer_ev);
ev_run(loop_ev, 0);
}
static void
foreign_event_loop_stop_libev(void)
{
ev_break(loop_ev, EVBREAK_ALL);
}
static void
foreign_event_loop_cleanup_libev(void)
{
/* cleanup the foreign loop assets */
ev_timer_stop(loop_ev, &timer_outer_ev);
ev_signal_stop(loop_ev, &sighandler_ev);
ev_run(loop_ev, 0);
ev_loop_destroy(loop_ev);
}
#endif
/* this is called at 1Hz using a foreign loop timer */
static void
void
foreign_timer_service(void *foreign_loop)
{
void *foreign_loops[1];
@ -377,22 +119,7 @@ foreign_timer_service(void *foreign_loop)
case TEST_STATE_EXIT:
lwsl_user("Deciding to exit foreign loop too\n");
#if defined(LWS_WITH_LIBUV)
if (info.options & LWS_SERVER_OPTION_LIBUV)
foreign_event_loop_stop_libuv();
#endif
#if defined(LWS_WITH_LIBEVENT)
if (info.options & LWS_SERVER_OPTION_LIBEVENT)
foreign_event_loop_stop_libevent();
#endif
#if defined(LWS_WITH_LIBEV)
if (info.options & LWS_SERVER_OPTION_LIBEV)
foreign_event_loop_stop_libev();
#endif
#if defined(LWS_WITH_GLIB)
if (info.options & LWS_SERVER_OPTION_GLIB)
foreign_event_loop_stop_glib();
#endif
ops->stop();
break;
default:
break;
@ -437,23 +164,45 @@ int main(int argc, const char **argv)
info.ssl_private_key_filepath = "localhost-100y.key";
}
if (lws_cmdline_option(argc, argv, "--uv"))
/*
* We configure lws to use the chosen event loop, and select the
* matching event-lib specific code for our demo operations
*/
#if defined(LWS_WITH_LIBUV)
if (lws_cmdline_option(argc, argv, "--uv")) {
info.options |= LWS_SERVER_OPTION_LIBUV;
else
if (lws_cmdline_option(argc, argv, "--event"))
ops = &ops_libuv;
lwsl_notice("%s: using libuv event loop\n", __func__);
} else
#endif
#if defined(LWS_WITH_LIBEVENT)
if (lws_cmdline_option(argc, argv, "--event")) {
info.options |= LWS_SERVER_OPTION_LIBEVENT;
else
if (lws_cmdline_option(argc, argv, "--ev"))
ops = &ops_libevent;
lwsl_notice("%s: using libevent loop\n", __func__);
} else
#endif
#if defined(LWS_WITH_LIBEV)
if (lws_cmdline_option(argc, argv, "--ev")) {
info.options |= LWS_SERVER_OPTION_LIBEV;
else
if (lws_cmdline_option(argc, argv, "--glib"))
ops = &ops_libev;
lwsl_notice("%s: using libev loop\n", __func__);
} else
#endif
#if defined(LWS_WITH_GLIB)
if (lws_cmdline_option(argc, argv, "--glib")) {
info.options |= LWS_SERVER_OPTION_GLIB;
else {
ops = &ops_glib;
lwsl_notice("%s: using glib 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");
return 1;
}
}
lwsl_user(" This app creates a foreign event loop with a timer +\n");
lwsl_user(" signalhandler, and performs a test in three phases:\n");
@ -469,43 +218,13 @@ int main(int argc, const char **argv)
/* foreign loop specific startup and run */
#if defined(LWS_WITH_LIBUV)
if (info.options & LWS_SERVER_OPTION_LIBUV)
foreign_event_loop_init_and_run_libuv();
#endif
#if defined(LWS_WITH_LIBEVENT)
if (info.options & LWS_SERVER_OPTION_LIBEVENT)
foreign_event_loop_init_and_run_libevent();
#endif
#if defined(LWS_WITH_LIBEV)
if (info.options & LWS_SERVER_OPTION_LIBEV)
foreign_event_loop_init_and_run_libev();
#endif
#if defined(LWS_WITH_GLIB)
if (info.options & LWS_SERVER_OPTION_GLIB)
foreign_event_loop_init_and_run_glib();
#endif
ops->init_and_run();
lws_context_destroy(context);
/* foreign loop specific cleanup and exit */
#if defined(LWS_WITH_LIBUV)
if (info.options & LWS_SERVER_OPTION_LIBUV)
foreign_event_loop_cleanup_libuv();
#endif
#if defined(LWS_WITH_LIBEVENT)
if (info.options & LWS_SERVER_OPTION_LIBEVENT)
foreign_event_loop_cleanup_libevent();
#endif
#if defined(LWS_WITH_LIBEV)
if (info.options & LWS_SERVER_OPTION_LIBEV)
foreign_event_loop_cleanup_libev();
#endif
#if defined(LWS_WITH_GLIB)
if (info.options & LWS_SERVER_OPTION_GLIB)
foreign_event_loop_cleanup_glib();
#endif
ops->cleanup();
lwsl_user("%s: exiting...\n", __func__);

View file

@ -0,0 +1,15 @@
struct ops {
void (*init_and_run)(void);
void (*stop)(void);
void (*cleanup)(void);
};
extern struct lws_context *context;
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;

View file

@ -396,7 +396,7 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state,
/* provide a hint about the payload size */
m->pos = 0;
m->len = strlen(postbody);
lws_ss_request_tx_len(m->ss, strlen(postbody));
lws_ss_request_tx_len(m->ss, (unsigned long)strlen(postbody));
break;
case LWSSSCS_CONNECTED:
lws_ss_request_tx(m->ss);

View file

@ -199,8 +199,9 @@ myss_srv_state(void *userobj, void *sh, lws_ss_constate_t state,
/*
* ...it's going to be whatever size it is (and request tx)
*/
lws_ss_request_tx_len(m->ss, multipart ? strlen(multipart_html) :
strlen(html));
lws_ss_request_tx_len(m->ss, (unsigned long)
(multipart ? strlen(multipart_html) :
strlen(html)));
break;
case LWSSSCS_SERVER_UPGRADE:

View file

@ -72,6 +72,7 @@
#endif
#include <string.h>
#include <fcntl.h>
struct per_vhost_data__raw_test {
struct lws_context *context;