mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
event-lib-glib
Adds support for glib event library.
This commit is contained in:
parent
2cb705f71f
commit
af2f1f9a87
27 changed files with 1143 additions and 20 deletions
|
@ -50,6 +50,7 @@ option(LWS_WITH_HTTP_BROTLI "Also offer brotli http stream compression (requires
|
|||
option(LWS_WITH_ACME "Enable support for ACME automatic cert acquisition + maintenance (letsencrypt etc)" OFF)
|
||||
option(LWS_WITH_HUBBUB "Enable libhubbub rewriting support" OFF)
|
||||
option(LWS_WITH_ALSA "Enable alsa audio example" OFF)
|
||||
option(LWS_WITH_GTK "Enable gtk example" OFF)
|
||||
option(LWS_WITH_FTS "Full Text Search support" OFF)
|
||||
option(LWS_WITH_SYS_ASYNC_DNS "Nonblocking internal IPv4 + IPv6 DNS resolver" OFF)
|
||||
option(LWS_WITH_SYS_NTPCLIENT "Build in tiny ntpclient good for tls date validation and run via lws_system" OFF)
|
||||
|
@ -69,6 +70,8 @@ option(LWS_SSL_CLIENT_USE_OS_CA_CERTS "SSL support should make use of the OS-ins
|
|||
option(LWS_WITH_LIBEV "Compile with support for libev" OFF)
|
||||
option(LWS_WITH_LIBUV "Compile with support for libuv" OFF)
|
||||
option(LWS_WITH_LIBEVENT "Compile with support for libevent" OFF)
|
||||
option(LWS_WITH_GLIB "Compile with support for glib event loop" OFF)
|
||||
|
||||
#
|
||||
# Static / Dynamic build options
|
||||
#
|
||||
|
@ -204,6 +207,7 @@ if(LWS_WITH_DISTRO_RECOMMENDED)
|
|||
set(LWS_WITH_RANGES 1)
|
||||
set(LWS_WITH_ACME 1)
|
||||
set(LWS_WITH_SERVER_STATUS 1)
|
||||
set(LWS_WITH_GLIB 1)
|
||||
set(LWS_WITH_LIBUV 1)
|
||||
set(LWS_WITH_LIBEV 1)
|
||||
# libev + libevent cannot coexist at build-time
|
||||
|
@ -365,7 +369,7 @@ if (LWS_WITH_MBEDTLS)
|
|||
include_directories(lib/tls/mbedtls/wrapper/include)
|
||||
endif()
|
||||
|
||||
include_directories(include plugins lib/core lib/core-net lib/event-libs include/abstract lib/tls lib/roles lib/event-libs/libuv lib/event-libs/poll lib/event-libs/libevent lib/event-libs/libev lib/jose/jwe lib/jose/jws lib/jose lib/misc lib/roles/http lib/roles/http/compression lib/roles/h1 lib/roles/h2 lib/roles/ws lib/roles/cgi lib/roles/dbus lib/roles/raw-proxy lib/abstract lib/system/async-dns)
|
||||
include_directories(include plugins lib/core lib/core-net lib/event-libs include/abstract lib/tls lib/roles lib/event-libs/libuv lib/event-libs/poll lib/event-libs/libevent lib/event-libs/glib lib/event-libs/libev lib/jose/jwe lib/jose/jws lib/jose lib/misc lib/roles/http lib/roles/http/compression lib/roles/h1 lib/roles/h2 lib/roles/ws lib/roles/cgi lib/roles/dbus lib/roles/raw-proxy lib/abstract lib/system/async-dns)
|
||||
|
||||
if (LWS_PLAT_FREERTOS)
|
||||
include_directories(lib/plat/freertos lib/plat/freertos/esp32)
|
||||
|
@ -544,6 +548,9 @@ set(LWS_SQLITE3_LIBRARIES CACHE PATH "Path to the sqlite3 library")
|
|||
set(LWS_SQLITE3_INCLUDE_DIRS CACHE PATH "Path to the sqlite3 include directory")
|
||||
set(LWS_LIBEVENT_INCLUDE_DIRS CACHE PATH "Path to the libevent include directory")
|
||||
set(LWS_LIBEVENT_LIBRARIES CACHE PATH "Path to the libevent library")
|
||||
set(LWS_GLIB_INCLUDE_DIRS CACHE PATH "Path to the glib include directory")
|
||||
set(LWS_GLIB_LIBRARIES CACHE PATH "Path to the glib library")
|
||||
|
||||
|
||||
|
||||
if (NOT LWS_WITH_SSL)
|
||||
|
@ -654,6 +661,15 @@ if (LWS_WITH_LIBEVENT)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_GLIB)
|
||||
if ("${LWS_GLIB_LIBRARIES}" STREQUAL "" OR "${LWS_GLIB_INCLUDE_DIRS}" STREQUAL "")
|
||||
else()
|
||||
set(LIBGLIB_LIBRARIES ${LWS_GLIB_LIBRARIES})
|
||||
set(LIBGLIB_INCLUDE_DIRS ${LWS_GLIB_INCLUDE_DIRS})
|
||||
set(LIBGLIB_FOUND 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_SQLITE3)
|
||||
if ("${LWS_SQLITE3_LIBRARIES}" STREQUAL "" OR "${LWS_SQLITE3_INCLUDE_DIRS}" STREQUAL "")
|
||||
else()
|
||||
|
@ -1454,6 +1470,12 @@ if (LWS_WITH_LIBEVENT AND LWS_WITH_NETWORK)
|
|||
lib/event-libs/libevent/libevent.c)
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_GLIB AND LWS_WITH_NETWORK)
|
||||
list(APPEND SOURCES
|
||||
lib/event-libs/glib/glib.c)
|
||||
endif()
|
||||
|
||||
|
||||
if (LWS_WITH_LIBEV AND LWS_WITH_NETWORK)
|
||||
list(APPEND SOURCES
|
||||
lib/event-libs/libev/libev.c)
|
||||
|
@ -1893,6 +1915,30 @@ if (LWS_WITH_LIBEVENT)
|
|||
list(APPEND LIB_LIST ${LIBEVENT_LIBRARIES})
|
||||
endif(LWS_WITH_LIBEVENT)
|
||||
|
||||
if (LWS_WITH_GLIB)
|
||||
include (FindPkgConfig)
|
||||
if (NOT GLIB_FOUND)
|
||||
find_path(GLIB_INCLUDE_DIRS NAMES glib-2.0/glib.h)
|
||||
find_library(GLIB_LIBRARIES NAMES glib-2.0)
|
||||
if(GLIB_INCLUDE_DIRS AND GLIB_LIBRARIES)
|
||||
set(GLIB_FOUND 1)
|
||||
endif()
|
||||
if (GLIB_INCLUDE_DIRS)
|
||||
set(GLIB_INCLUDE_DIRS "${GLIB_INCLUDE_DIRS}/glib-2.0")
|
||||
endif()
|
||||
endif()
|
||||
PKG_SEARCH_MODULE(LWS_GLIB2 glib-2.0)
|
||||
if (LWS_GLIB2_FOUND)
|
||||
list(APPEND GLIB_INCLUDE_DIRS "${LWS_GLIB2_INCLUDE_DIRS}")
|
||||
endif()
|
||||
message("glib include dir: ${GLIB_INCLUDE_DIRS}")
|
||||
message("glib libraries: ${GLIB_LIBRARIES}")
|
||||
include_directories("${GLIB_INCLUDE_DIRS}")
|
||||
list(APPEND LIB_LIST ${GLIB_LIBRARIES})
|
||||
endif(LWS_WITH_GLIB)
|
||||
|
||||
|
||||
|
||||
if (LWS_WITH_SQLITE3)
|
||||
if (NOT SQLITE3_FOUND)
|
||||
find_path(SQLITE3_INCLUDE_DIRS NAMES sqlite3.h)
|
||||
|
@ -2462,7 +2508,7 @@ if (LWS_WITH_GENERIC_SESSIONS AND LWS_ROLE_WS AND LWS_WITH_TLS)
|
|||
target_link_libraries(protocol_lws_messageboard sqlite3 )
|
||||
endif(WIN32)
|
||||
|
||||
endif(LWS_WITH_GENERIC_SESSIONS AND LWS_ROLE_WS)
|
||||
endif(LWS_WITH_GENERIC_SESSIONS AND LWS_ROLE_WS AND LWS_WITH_TLS)
|
||||
|
||||
|
||||
endif(LWS_WITH_PLUGINS AND LWS_WITH_SHARED)
|
||||
|
@ -2790,6 +2836,7 @@ message(" LWS_WITHOUT_DAEMONIZE = ${LWS_WITHOUT_DAEMONIZE}")
|
|||
message(" LWS_WITH_LIBEV = ${LWS_WITH_LIBEV}")
|
||||
message(" LWS_WITH_LIBUV = ${LWS_WITH_LIBUV}")
|
||||
message(" LWS_WITH_LIBEVENT = ${LWS_WITH_LIBEVENT}")
|
||||
message(" LWS_WITH_GLIB = ${LWS_WITH_GLIB}")
|
||||
message(" LWS_IPV6 = ${LWS_IPV6}")
|
||||
message(" LWS_UNIX_SOCK = ${LWS_UNIX_SOCK}")
|
||||
message(" LWS_WITH_HTTP2 = ${LWS_WITH_HTTP2}")
|
||||
|
|
14
README.md
14
README.md
|
@ -16,6 +16,20 @@ various scenarios, CC0-licensed (public domain) for cut-and-paste, allow you to
|
|||
News
|
||||
----
|
||||
|
||||
## libglib native event loop support
|
||||
|
||||
glib's event loop joins libuv, libevent and libev support in lws for both the
|
||||
`lws_context` creating and owning the loop object for its lifetime, and for
|
||||
an already-existing "foreign loop" where the `lws_context` is created, attaches,
|
||||
detaches, and is destroyed without affecting the loop.
|
||||
|
||||
This allows direct, lock-free integration of lws functionality with, eg, a GTK app's
|
||||
existing `GMainLoop` / glib `g_main_loop`. Just select `-DLWS_WITH_GLIB=1` at cmake
|
||||
time to enable. The -eventlib minimal examples also support --glib option to
|
||||
select using the glib loop at runtime.
|
||||
|
||||
There's also a gtk example that is built if lws cmake has `-DLWS_WITH_GTK=1`.
|
||||
|
||||
## `lws_system` helper for attaching code to a single event loop from another thread
|
||||
|
||||
`lws_system` ops struct now has a member that enables other threads (in the
|
||||
|
|
|
@ -110,6 +110,8 @@
|
|||
#cmakedefine LWS_WITH_FTS
|
||||
#cmakedefine LWS_WITH_GENCRYPTO
|
||||
#cmakedefine LWS_WITH_GENERIC_SESSIONS
|
||||
#cmakedefine LWS_WITH_GLIB
|
||||
#cmakedefine LWS_WITH_GTK
|
||||
#cmakedefine LWS_WITH_HTTP2
|
||||
#cmakedefine LWS_WITH_HTTP_BROTLI
|
||||
#cmakedefine LWS_WITH_HTTP_PROXY
|
||||
|
|
|
@ -218,6 +218,9 @@
|
|||
* poll mode.
|
||||
*/
|
||||
|
||||
#define LWS_SERVER_OPTION_GLIB (1ll << 33)
|
||||
/**< (CTX) Use glib event loop */
|
||||
|
||||
/****** add new things just above ---^ ******/
|
||||
|
||||
|
||||
|
|
|
@ -507,7 +507,7 @@ just_kill_connection:
|
|||
if (!wsi->socket_is_permanently_unusable &&
|
||||
lws_socket_is_valid(wsi->desc.sockfd) &&
|
||||
lwsi_state(wsi) != LRS_SHUTDOWN &&
|
||||
context->event_loop_ops->periodic_events_available) {
|
||||
(context->event_loop_ops->flags & LELOF_ISPOLL)) {
|
||||
__lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN);
|
||||
lwsi_set_state(wsi, LRS_SHUTDOWN);
|
||||
__lws_set_timeout(wsi, PENDING_TIMEOUT_SHUTDOWN_FLUSH,
|
||||
|
|
|
@ -73,7 +73,8 @@ _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_LIBEVENT) && \
|
||||
!defined(LWS_WITH_GLIB)
|
||||
/*
|
||||
* This only applies when we use the default poll() event loop.
|
||||
*
|
||||
|
|
|
@ -429,6 +429,9 @@ struct lws_context_per_thread {
|
|||
#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)
|
||||
|
@ -649,7 +652,7 @@ struct lws {
|
|||
/* lifetime members */
|
||||
|
||||
#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBUV) || \
|
||||
defined(LWS_WITH_LIBEVENT)
|
||||
defined(LWS_WITH_LIBEVENT) || defined(LWS_WITH_GLIB)
|
||||
struct lws_io_watcher w_read;
|
||||
#endif
|
||||
#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBEVENT)
|
||||
|
|
|
@ -409,6 +409,13 @@ lws_create_context(const struct lws_context_creation_info *info)
|
|||
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;
|
||||
|
||||
|
|
|
@ -207,6 +207,9 @@ struct lws_io_watcher {
|
|||
#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;
|
||||
|
||||
|
@ -222,6 +225,9 @@ struct lws_signal_watcher {
|
|||
#endif
|
||||
#ifdef LWS_WITH_LIBEVENT
|
||||
struct lws_signal_watcher_libevent event;
|
||||
#endif
|
||||
#ifdef LWS_WITH_LIBEVENT
|
||||
struct lws_signal_watcher_glib glib;
|
||||
#endif
|
||||
struct lws_context *context;
|
||||
};
|
||||
|
@ -339,6 +345,9 @@ struct lws_context {
|
|||
#if defined(LWS_WITH_LIBEVENT)
|
||||
struct lws_context_eventlibs_libevent event;
|
||||
#endif
|
||||
#if defined(LWS_WITH_GLIB)
|
||||
struct lws_context_eventlibs_glib glib;
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_TLS)
|
||||
struct lws_context_tls tls;
|
||||
|
|
464
lib/event-libs/glib/glib.c
Normal file
464
lib/event-libs/glib/glib.c
Normal file
|
@ -0,0 +1,464 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "private-lib-core.h"
|
||||
|
||||
#include <glib-unix.h>
|
||||
|
||||
#define wsi_to_subclass(_w) ((_w)->w_read.glib.source)
|
||||
#define wsi_to_gsource(_w) ((GSource *)wsi_to_subclass(_w))
|
||||
#define pt_to_loop(_pt) ((_pt)->glib.loop)
|
||||
#define pt_to_g_main_context(_pt) g_main_loop_get_context(pt_to_loop(_pt))
|
||||
|
||||
static gboolean
|
||||
lws_glib_idle_timer_cb(void *p);
|
||||
|
||||
static gboolean
|
||||
lws_glib_hrtimer_cb(void *p);
|
||||
|
||||
static gboolean
|
||||
lws_glib_check(GSource *src)
|
||||
{
|
||||
struct lws_io_watcher_glib_subclass *sub =
|
||||
(struct lws_io_watcher_glib_subclass *)src;
|
||||
|
||||
return !!g_source_query_unix_fd(src, sub->tag);
|
||||
}
|
||||
|
||||
/*
|
||||
* These helpers attach only to the main_context that belongs to the pt's glib
|
||||
* mainloop. The simpler g_timeout_add() and g_idle_add() are forbidden
|
||||
* because they implicitly choose the default main context to attach to
|
||||
* instead of specifically the loop bound to the pt.
|
||||
*
|
||||
* https://developer.gnome.org/programming-guidelines/unstable/main-contexts.html.en#what-is-gmaincontext
|
||||
*/
|
||||
|
||||
static int
|
||||
lws_glib_set_idle(struct lws_context_per_thread *pt)
|
||||
{
|
||||
GSource *gis;
|
||||
|
||||
if (pt->glib.idle_tag)
|
||||
return 0;
|
||||
|
||||
gis = g_idle_source_new();
|
||||
if (!gis)
|
||||
return 1;
|
||||
|
||||
g_source_set_callback(gis, lws_glib_idle_timer_cb, pt, NULL);
|
||||
pt->glib.idle_tag = g_source_attach(gis, pt_to_g_main_context(pt));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lws_glib_set_timeout(struct lws_context_per_thread *pt, unsigned int ms)
|
||||
{
|
||||
GSource *gts;
|
||||
|
||||
gts = g_timeout_source_new(ms);
|
||||
if (!gts)
|
||||
return 1;
|
||||
|
||||
g_source_set_callback(gts, lws_glib_hrtimer_cb, pt, NULL);
|
||||
pt->glib.hrtimer_tag = g_source_attach(gts, pt_to_g_main_context(pt));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lws_glib_dispatch(GSource *src, GSourceFunc x, gpointer userData)
|
||||
{
|
||||
struct lws_io_watcher_glib_subclass *sub =
|
||||
(struct lws_io_watcher_glib_subclass *)src;
|
||||
struct lws_context_per_thread *pt;
|
||||
struct lws_pollfd eventfd;
|
||||
GIOCondition cond;
|
||||
|
||||
cond = g_source_query_unix_fd(src, sub->tag);
|
||||
eventfd.revents = cond;
|
||||
|
||||
/* translate from glib event namespace to platform */
|
||||
|
||||
if (cond & G_IO_IN)
|
||||
eventfd.revents |= LWS_POLLIN;
|
||||
if (cond & G_IO_OUT)
|
||||
eventfd.revents |= LWS_POLLOUT;
|
||||
if (cond & G_IO_ERR)
|
||||
eventfd.revents |= LWS_POLLHUP;
|
||||
if (cond & G_IO_HUP)
|
||||
eventfd.revents |= LWS_POLLHUP;
|
||||
|
||||
eventfd.events = eventfd.revents;
|
||||
eventfd.fd = sub->wsi->desc.sockfd;
|
||||
|
||||
lwsl_debug("%s: wsi %p: fd %d, events %d\n", __func__, sub->wsi,
|
||||
eventfd.fd, eventfd.revents);
|
||||
|
||||
pt = &sub->wsi->context->pt[(int)sub->wsi->tsi];
|
||||
if (pt->is_destroyed)
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
lws_service_fd_tsi(sub->wsi->context, &eventfd, sub->wsi->tsi);
|
||||
|
||||
if (!pt->glib.idle_tag)
|
||||
lws_glib_set_idle(pt);
|
||||
|
||||
if (pt->destroy_self)
|
||||
lws_context_destroy(pt->context);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static const GSourceFuncs lws_glib_source_ops = {
|
||||
.prepare = NULL,
|
||||
.check = lws_glib_check,
|
||||
.dispatch = lws_glib_dispatch,
|
||||
.finalize = NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the callback for a timer object that is set to the earliest scheduled
|
||||
* lws event... it services any lws scheduled events that are ready, and then
|
||||
* resets the event loop timer to the earliest remaining event, if any.
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
lws_glib_hrtimer_cb(void *p)
|
||||
{
|
||||
struct lws_context_per_thread *pt = (struct lws_context_per_thread *)p;
|
||||
unsigned int ms;
|
||||
lws_usec_t us;
|
||||
|
||||
lws_pt_lock(pt, __func__);
|
||||
us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs());
|
||||
if (us) {
|
||||
ms = us / LWS_US_PER_MS;
|
||||
if (!ms)
|
||||
ms = 1;
|
||||
|
||||
lws_glib_set_timeout(pt, ms);
|
||||
}
|
||||
|
||||
lws_pt_unlock(pt);
|
||||
|
||||
lws_glib_set_idle(pt);
|
||||
|
||||
return FALSE; /* stop it repeating */
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lws_glib_idle_timer_cb(void *p)
|
||||
{
|
||||
struct lws_context_per_thread *pt = (struct lws_context_per_thread *)p;
|
||||
|
||||
if (pt->is_destroyed)
|
||||
return FALSE;
|
||||
|
||||
lws_service_do_ripe_rxflow(pt);
|
||||
lws_glib_hrtimer_cb(pt);
|
||||
|
||||
/*
|
||||
* is there anybody with pending stuff that needs service forcing?
|
||||
*/
|
||||
if (!lws_service_adjust_timeout(pt->context, 1, pt->tid)) {
|
||||
/* -1 timeout means just do forced service */
|
||||
_lws_plat_service_forced_tsi(pt->context, pt->tid);
|
||||
/* still somebody left who wants forced service? */
|
||||
if (!lws_service_adjust_timeout(pt->context, 1, pt->tid))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (pt->destroy_self)
|
||||
lws_context_destroy(pt->context);
|
||||
|
||||
/*
|
||||
* For glib, this disables the idle callback. Otherwise we keep
|
||||
* coming back here immediately endlessly.
|
||||
*
|
||||
* We reenable the idle callback on the next network or scheduled event
|
||||
*/
|
||||
|
||||
pt->glib.idle_tag = 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
lws_glib_sigint_cb(void *ctx)
|
||||
{
|
||||
struct lws_context_per_thread *pt = ctx;
|
||||
|
||||
pt->inside_service = 1;
|
||||
|
||||
if (pt->context->eventlib_signal_cb) {
|
||||
pt->context->eventlib_signal_cb(NULL, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
if (!pt->event_loop_foreign)
|
||||
g_main_loop_quit(pt_to_loop(pt));
|
||||
}
|
||||
|
||||
static int
|
||||
elops_init_context_glib(struct lws_context *context,
|
||||
const struct lws_context_creation_info *info)
|
||||
{
|
||||
int n;
|
||||
|
||||
context->eventlib_signal_cb = info->signal_cb;
|
||||
|
||||
for (n = 0; n < context->count_threads; n++)
|
||||
context->pt[n].w_sigint.context = context;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
elops_accept_glib(struct lws *wsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
int fd;
|
||||
|
||||
assert(!wsi_to_subclass(wsi));
|
||||
|
||||
wsi_to_subclass(wsi) = (struct lws_io_watcher_glib_subclass *)
|
||||
g_source_new((GSourceFuncs *)&lws_glib_source_ops,
|
||||
sizeof(*wsi_to_subclass(wsi)));
|
||||
if (!wsi_to_subclass(wsi))
|
||||
return 1;
|
||||
|
||||
wsi->w_read.context = wsi->context;
|
||||
wsi_to_subclass(wsi)->wsi = wsi;
|
||||
|
||||
if (wsi->role_ops->file_handle)
|
||||
fd = wsi->desc.filefd;
|
||||
else
|
||||
fd = wsi->desc.sockfd;
|
||||
|
||||
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;
|
||||
|
||||
g_source_set_callback(wsi_to_gsource(wsi),
|
||||
G_SOURCE_FUNC(lws_service_fd), wsi->context, NULL);
|
||||
|
||||
g_source_attach(wsi_to_gsource(wsi), pt_to_g_main_context(pt));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
elops_init_pt_glib(struct lws_context *context, void *_loop, int tsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &context->pt[tsi];
|
||||
struct lws_vhost *vh = context->vhost_list;
|
||||
GMainLoop *loop = (GMainLoop *)_loop;
|
||||
|
||||
if (!loop)
|
||||
loop = g_main_loop_new(NULL, 0);
|
||||
else
|
||||
context->pt[tsi].event_loop_foreign = 1;
|
||||
|
||||
if (!loop) {
|
||||
lwsl_err("%s: creating glib loop failed\n", __func__);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
pt->glib.loop = loop;
|
||||
|
||||
/*
|
||||
* Initialize all events with the listening sockets
|
||||
* and register a callback for read operations
|
||||
*/
|
||||
|
||||
while (vh) {
|
||||
if (vh->lserv_wsi)
|
||||
elops_accept_glib(vh->lserv_wsi);
|
||||
|
||||
vh = vh->vhost_next;
|
||||
}
|
||||
|
||||
lws_glib_set_idle(pt);
|
||||
|
||||
/* Register the signal watcher unless it's a foreign loop */
|
||||
|
||||
if (pt->event_loop_foreign)
|
||||
return 0;
|
||||
|
||||
pt->glib.sigint_tag = g_unix_signal_add(SIGINT,
|
||||
G_SOURCE_FUNC(lws_glib_sigint_cb), pt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are changing the event wait for this guy
|
||||
*/
|
||||
|
||||
static void
|
||||
elops_io_glib(struct lws *wsi, int flags)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
GIOCondition cond = wsi->w_read.actual_events | G_IO_ERR;
|
||||
|
||||
if (!pt_to_loop(pt) || wsi->context->being_destroyed || pt->is_destroyed)
|
||||
return;
|
||||
|
||||
/*
|
||||
* We are being given individual set / clear operations using
|
||||
* LWS_EV_ common namespace, convert them to glib namespace bitfield
|
||||
*/
|
||||
|
||||
if (flags & LWS_EV_READ) {
|
||||
if (flags & LWS_EV_STOP)
|
||||
cond &= ~(G_IO_IN | G_IO_HUP);
|
||||
else
|
||||
cond |= G_IO_IN | G_IO_HUP;
|
||||
}
|
||||
|
||||
if (flags & LWS_EV_WRITE) {
|
||||
if (flags & LWS_EV_STOP)
|
||||
cond &= ~G_IO_OUT;
|
||||
else
|
||||
cond |= G_IO_OUT;
|
||||
}
|
||||
|
||||
wsi->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);
|
||||
|
||||
g_source_modify_unix_fd(wsi_to_gsource(wsi), wsi_to_subclass(wsi)->tag,
|
||||
cond);
|
||||
}
|
||||
|
||||
static void
|
||||
elops_run_pt_glib(struct lws_context *context, int tsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &context->pt[tsi];
|
||||
|
||||
if (pt_to_loop(pt))
|
||||
g_main_loop_run(pt_to_loop(pt));
|
||||
}
|
||||
|
||||
static void
|
||||
elops_destroy_wsi_glib(struct lws *wsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt;
|
||||
|
||||
if (!wsi)
|
||||
return;
|
||||
|
||||
pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
if (pt->is_destroyed)
|
||||
return;
|
||||
|
||||
if (!wsi_to_gsource(wsi))
|
||||
return;
|
||||
|
||||
if (wsi_to_subclass(wsi)->tag) {
|
||||
g_source_remove_unix_fd(wsi_to_gsource(wsi),
|
||||
wsi_to_subclass(wsi)->tag);
|
||||
wsi_to_subclass(wsi)->tag = NULL;
|
||||
}
|
||||
|
||||
g_source_destroy(wsi_to_gsource(wsi));
|
||||
wsi_to_subclass(wsi) = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
elops_destroy_pt_glib(struct lws_context *context, int tsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &context->pt[tsi];
|
||||
struct lws_vhost *vh = context->vhost_list;
|
||||
|
||||
if (!pt_to_loop(pt))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Free all events with the listening sockets
|
||||
*/
|
||||
while (vh) {
|
||||
if (vh->lserv_wsi)
|
||||
elops_destroy_wsi_glib(vh->lserv_wsi);
|
||||
|
||||
vh = vh->vhost_next;
|
||||
}
|
||||
|
||||
if (pt->glib.hrtimer_tag)
|
||||
g_source_remove(pt->glib.hrtimer_tag);
|
||||
|
||||
if (!pt->event_loop_foreign) {
|
||||
g_main_loop_quit(pt_to_loop(pt));
|
||||
g_source_remove(pt->glib.sigint_tag);
|
||||
g_main_loop_unref(pt_to_loop(pt));
|
||||
}
|
||||
|
||||
pt_to_loop(pt) = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
elops_destroy_context2_glib(struct lws_context *context)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &context->pt[0];
|
||||
int n;
|
||||
|
||||
for (n = 0; n < (int)context->count_threads; n++) {
|
||||
if (!pt->event_loop_foreign)
|
||||
g_main_loop_quit(pt_to_loop(pt));
|
||||
pt++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
elops_wsi_logical_close_glib(struct lws *wsi)
|
||||
{
|
||||
elops_destroy_wsi_glib(wsi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct lws_event_loop_ops event_loop_ops_glib = {
|
||||
/* name */ "glib",
|
||||
/* init_context */ elops_init_context_glib,
|
||||
/* destroy_context1 */ NULL,
|
||||
/* destroy_context2 */ elops_destroy_context2_glib,
|
||||
/* init_vhost_listen_wsi */ elops_accept_glib,
|
||||
/* init_pt */ elops_init_pt_glib,
|
||||
/* wsi_logical_close */ elops_wsi_logical_close_glib,
|
||||
/* check_client_connect_ok */ NULL,
|
||||
/* close_handle_manually */ NULL,
|
||||
/* accept */ elops_accept_glib,
|
||||
/* io */ elops_io_glib,
|
||||
/* run_pt */ elops_run_pt_glib,
|
||||
/* destroy_pt */ elops_destroy_pt_glib,
|
||||
/* destroy wsi */ elops_destroy_wsi_glib,
|
||||
|
||||
/* flags */ LELOF_DESTROY_FINAL,
|
||||
};
|
54
lib/event-libs/glib/private-lib-event-libs-glib.h
Normal file
54
lib/event-libs/glib/private-lib-event-libs-glib.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if defined(LWS_WITH_GLIB)
|
||||
#include <glib-2.0/glib.h>
|
||||
#endif /* LWS_WITH_GLIB */
|
||||
|
||||
struct lws_pt_eventlibs_glib {
|
||||
GMainLoop *loop;
|
||||
guint hrtimer_tag;
|
||||
guint sigint_tag;
|
||||
guint idle_tag;
|
||||
};
|
||||
|
||||
struct lws_io_watcher_glib_subclass {
|
||||
GSource base;
|
||||
struct lws *wsi;
|
||||
gpointer tag;
|
||||
};
|
||||
|
||||
/*
|
||||
* One of these is embedded in each wsi
|
||||
*/
|
||||
|
||||
struct lws_io_watcher_glib {
|
||||
struct lws_io_watcher_glib_subclass *source; /* these are created and destroyed by glib */
|
||||
};
|
||||
|
||||
struct lws_context_eventlibs_glib {
|
||||
//int placeholder;
|
||||
};
|
||||
|
||||
extern struct lws_event_loop_ops event_loop_ops_glib;
|
|
@ -382,5 +382,5 @@ struct lws_event_loop_ops event_loop_ops_ev = {
|
|||
/* destroy_pt */ elops_destroy_pt_ev,
|
||||
/* destroy wsi */ elops_destroy_wsi_ev,
|
||||
|
||||
/* periodic_events_available */ 0,
|
||||
/* flags */ 0,
|
||||
};
|
||||
|
|
|
@ -453,5 +453,5 @@ struct lws_event_loop_ops event_loop_ops_event = {
|
|||
/* destroy_pt */ elops_destroy_pt_event,
|
||||
/* destroy wsi */ elops_destroy_wsi_event,
|
||||
|
||||
/* periodic_events_available */ 0,
|
||||
/* flags */ 0,
|
||||
};
|
||||
|
|
|
@ -976,5 +976,5 @@ struct lws_event_loop_ops event_loop_ops_uv = {
|
|||
/* destroy_pt */ elops_destroy_pt_uv,
|
||||
/* destroy wsi */ NULL,
|
||||
|
||||
/* periodic_events_available */ 0,
|
||||
/* flags */ 0,
|
||||
};
|
||||
|
|
|
@ -42,5 +42,5 @@ struct lws_event_loop_ops event_loop_ops_poll = {
|
|||
/* destroy_pt */ NULL,
|
||||
/* destroy wsi */ NULL,
|
||||
|
||||
/* periodic_events_available */ 1,
|
||||
/* flags */ LELOF_ISPOLL,
|
||||
};
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
* This is included from private-lib-core.h
|
||||
*/
|
||||
|
||||
enum lws_event_lib_ops_flags {
|
||||
LELOF_ISPOLL = (1 >> 0),
|
||||
LELOF_DESTROY_FINAL = (1 >> 1),
|
||||
};
|
||||
|
||||
struct lws_event_loop_ops {
|
||||
const char *name;
|
||||
/* event loop-specific context init during context creation */
|
||||
|
@ -54,7 +59,7 @@ struct lws_event_loop_ops {
|
|||
/* called just before wsi is freed */
|
||||
void (*destroy_wsi)(struct lws *wsi);
|
||||
|
||||
unsigned int periodic_events_available:1;
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
/* bring in event libs private declarations */
|
||||
|
@ -71,6 +76,10 @@ struct lws_event_loop_ops {
|
|||
#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
|
||||
|
|
|
@ -2341,8 +2341,8 @@ lws_http_transaction_completed(struct lws *wsi)
|
|||
* until we can verify POLLOUT. The part of this that confirms POLLOUT
|
||||
* with no partials is in lws_server_socket_service() below.
|
||||
*/
|
||||
lwsl_debug("%s: %p: setting DEF_ACT from 0x%x\n", __func__,
|
||||
wsi, (int)wsi->wsistate);
|
||||
lwsl_debug("%s: %p: setting DEF_ACT from 0x%x: %p\n", __func__,
|
||||
wsi, (int)wsi->wsistate, wsi->buflist);
|
||||
lwsi_set_state(wsi, LRS_DEFERRING_ACTION);
|
||||
wsi->http.tx_content_length = 0;
|
||||
wsi->http.tx_content_remain = 0;
|
||||
|
|
102
minimal-examples/gtk/minimal-gtk/CMakeLists.txt
Normal file
102
minimal-examples/gtk/minimal-gtk/CMakeLists.txt
Normal file
|
@ -0,0 +1,102 @@
|
|||
project(lws-minimal-gtk)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
set(SAMP lws-minimal-gtk)
|
||||
set(SRCS main.c)
|
||||
|
||||
|
||||
# If we are being built as part of lws, confirm current build config supports
|
||||
# reqconfig, else skip building ourselves.
|
||||
#
|
||||
# If we are being built externally, confirm installed lws was configured to
|
||||
# support reqconfig, else error out with a helpful message about the problem.
|
||||
#
|
||||
MACRO(require_lws_config reqconfig _val result)
|
||||
|
||||
if (DEFINED ${reqconfig})
|
||||
if (${reqconfig})
|
||||
set (rq 1)
|
||||
else()
|
||||
set (rq 0)
|
||||
endif()
|
||||
else()
|
||||
set(rq 0)
|
||||
endif()
|
||||
|
||||
if (${_val} EQUAL ${rq})
|
||||
set(SAME 1)
|
||||
else()
|
||||
set(SAME 0)
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME})
|
||||
if (${_val})
|
||||
message("${SAMP}: skipping as lws being built without ${reqconfig}")
|
||||
else()
|
||||
message("${SAMP}: skipping as lws built with ${reqconfig}")
|
||||
endif()
|
||||
set(${result} 0)
|
||||
else()
|
||||
if (LWS_WITH_MINIMAL_EXAMPLES)
|
||||
set(MET ${SAME})
|
||||
else()
|
||||
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig})
|
||||
if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig})
|
||||
set(HAS_${reqconfig} 0)
|
||||
else()
|
||||
set(HAS_${reqconfig} 1)
|
||||
endif()
|
||||
if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val}))
|
||||
set(MET 1)
|
||||
else()
|
||||
set(MET 0)
|
||||
endif()
|
||||
endif()
|
||||
if (NOT MET)
|
||||
if (${_val})
|
||||
message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}")
|
||||
else()
|
||||
message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
ENDMACRO()
|
||||
|
||||
set(requirements 1)
|
||||
require_lws_config(LWS_ROLE_H1 1 requirements)
|
||||
require_lws_config(LWS_WITH_SERVER 1 requirements)
|
||||
require_lws_config(LWS_WITH_GLIB 1 requirements)
|
||||
require_lws_config(LWS_WITH_GTK 1 requirements)
|
||||
|
||||
if (requirements)
|
||||
|
||||
# gtk pieces
|
||||
|
||||
include (FindPkgConfig)
|
||||
|
||||
set(LWS_GTK_INCLUDE_DIRS CACHE PATH "Path to the gtk include directory")
|
||||
set(LWS_GTK_LIBRARIES CACHE PATH "Path to the gtk library")
|
||||
PKG_SEARCH_MODULE(LWS_GTK2 gtk+-3.0)
|
||||
if (LWS_GTK2_FOUND)
|
||||
list(APPEND LWS_GTK_INCLUDE_DIRS "${LWS_GTK2_INCLUDE_DIRS}")
|
||||
list(APPEND LWS_GTK_LIBRARIES "${LWS_GTK2_LIBRARIES}")
|
||||
endif()
|
||||
message("gtk include dir: ${LWS_GTK_INCLUDE_DIRS}")
|
||||
message("gtk libraries: ${LWS_GTK_LIBRARIES}")
|
||||
include_directories("${LWS_GTK_INCLUDE_DIRS}")
|
||||
set(extralibs ${extralibs} ${LWS_GTK_LIBRARIES})
|
||||
|
||||
|
||||
|
||||
message("Extra libs: ${extralibs}")
|
||||
|
||||
add_executable(${SAMP} ${SRCS})
|
||||
|
||||
if (websockets_shared)
|
||||
target_link_libraries(${SAMP} websockets_shared ${extralibs})
|
||||
add_dependencies(${SAMP} websockets_shared)
|
||||
else()
|
||||
target_link_libraries(${SAMP} websockets ${extralibs})
|
||||
endif()
|
||||
endif()
|
32
minimal-examples/gtk/minimal-gtk/README.md
Normal file
32
minimal-examples/gtk/minimal-gtk/README.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
# lws minimal http client gtk
|
||||
|
||||
The application goes to https://warmcat.com and receives the page data,
|
||||
from inside a gtk app using gtk / glib main loop directly.
|
||||
|
||||
## build
|
||||
|
||||
```
|
||||
$ cmake . && make
|
||||
```
|
||||
|
||||
## usage
|
||||
|
||||
|
||||
```
|
||||
$
|
||||
t1_main: started
|
||||
[2020/02/08 18:04:07:6647] N: Loading client CA for verification ./warmcat.com.cer
|
||||
[2020/02/08 18:04:07:7744] U: Connected to 46.105.127.147, http response: 200
|
||||
[2020/02/08 18:04:07:7762] U: RECEIVE_CLIENT_HTTP_READ: read 4087
|
||||
[2020/02/08 18:04:07:7762] U: RECEIVE_CLIENT_HTTP_READ: read 4096
|
||||
[2020/02/08 18:04:07:7928] U: RECEIVE_CLIENT_HTTP_READ: read 4087
|
||||
[2020/02/08 18:04:07:7929] U: RECEIVE_CLIENT_HTTP_READ: read 4096
|
||||
[2020/02/08 18:04:07:7956] U: RECEIVE_CLIENT_HTTP_READ: read 4087
|
||||
[2020/02/08 18:04:07:7956] U: RECEIVE_CLIENT_HTTP_READ: read 4096
|
||||
[2020/02/08 18:04:07:7956] U: RECEIVE_CLIENT_HTTP_READ: read 1971
|
||||
[2020/02/08 18:04:07:7956] U: LWS_CALLBACK_COMPLETED_CLIENT_HTTP
|
||||
Hello World
|
||||
$
|
||||
```
|
||||
|
||||
|
210
minimal-examples/gtk/minimal-gtk/main.c
Normal file
210
minimal-examples/gtk/minimal-gtk/main.c
Normal file
|
@ -0,0 +1,210 @@
|
|||
#include <gtk/gtk.h>
|
||||
#include <libwebsockets.h>
|
||||
|
||||
static int status = 0;
|
||||
|
||||
static void
|
||||
print_hello(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
g_print("Hello World\n");
|
||||
}
|
||||
|
||||
static void
|
||||
activate(GtkApplication *app, gpointer user_data)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *button, *bbox;
|
||||
|
||||
window = gtk_application_window_new(app);
|
||||
gtk_window_set_title(GTK_WINDOW(window), "mywindow");
|
||||
gtk_window_set_default_size(GTK_WINDOW(window), 200, 200);
|
||||
|
||||
bbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
|
||||
gtk_container_add(GTK_CONTAINER(window), bbox);
|
||||
|
||||
button = gtk_button_new_with_label("Hello World");
|
||||
g_signal_connect(button, "clicked", G_CALLBACK(print_hello), NULL);
|
||||
g_signal_connect_swapped(button, "clicked",
|
||||
G_CALLBACK(gtk_widget_destroy), window);
|
||||
gtk_container_add(GTK_CONTAINER(bbox), button);
|
||||
|
||||
gtk_widget_show_all(window);
|
||||
}
|
||||
|
||||
static int
|
||||
system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link,
|
||||
int current, int target)
|
||||
{
|
||||
struct lws_context *context = mgr->parent;
|
||||
struct lws_client_connect_info i;
|
||||
|
||||
if (current != LWS_SYSTATE_OPERATIONAL ||
|
||||
target != LWS_SYSTATE_OPERATIONAL)
|
||||
return 0;
|
||||
|
||||
lwsl_notice("%s: operational\n", __func__);
|
||||
|
||||
memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */
|
||||
i.context = context;
|
||||
i.ssl_connection = LCCSCF_USE_SSL | LCCSCF_H2_QUIRK_OVERFLOWS_TXCR |
|
||||
LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM;
|
||||
i.port = 443;
|
||||
i.address = "warmcat.com";
|
||||
i.path = "/";
|
||||
i.host = i.address;
|
||||
i.origin = i.address;
|
||||
i.method = "GET";
|
||||
|
||||
i.protocol = "http";
|
||||
|
||||
return !lws_client_connect_via_info(&i);
|
||||
}
|
||||
|
||||
static int
|
||||
callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
switch (reason) {
|
||||
|
||||
/* because we are protocols[0] ... */
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
lwsl_err("CLIENT_CONNECTION_ERROR: %s\n",
|
||||
in ? (char *)in : "(null)");
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
|
||||
{
|
||||
char buf[128];
|
||||
|
||||
lws_get_peer_simple(wsi, buf, sizeof(buf));
|
||||
status = lws_http_client_http_response(wsi);
|
||||
|
||||
lwsl_user("Connected to %s, http response: %d\n",
|
||||
buf, status);
|
||||
}
|
||||
break;
|
||||
|
||||
/* chunks of chunked content, with header removed */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
|
||||
lwsl_user("RECEIVE_CLIENT_HTTP_READ: read %d\n", (int)len);
|
||||
return 0; /* don't passthru */
|
||||
|
||||
/* uninterpreted http content */
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
|
||||
{
|
||||
char buffer[1024 + LWS_PRE];
|
||||
char *px = buffer + LWS_PRE;
|
||||
int lenx = sizeof(buffer) - LWS_PRE;
|
||||
|
||||
if (lws_http_client_read(wsi, &px, &lenx) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0; /* don't passthru */
|
||||
|
||||
case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
|
||||
lwsl_user("LWS_CALLBACK_COMPLETED_CLIENT_HTTP\n");
|
||||
lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
|
||||
lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return lws_callback_http_dummy(wsi, reason, user, in, len);
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"http",
|
||||
callback_http,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static gpointer
|
||||
t1_main (gpointer user_data)
|
||||
{
|
||||
lws_state_notify_link_t notifier = { {}, system_notify_cb, "app" };
|
||||
lws_state_notify_link_t *na[] = { ¬ifier, NULL };
|
||||
GMainContext *t1_mc = (GMainContext *)user_data;
|
||||
struct lws_context_creation_info info;
|
||||
struct lws_context *context;
|
||||
void *foreign_loops[1];
|
||||
GMainLoop *ml;
|
||||
|
||||
g_print("%s: started\n", __func__);
|
||||
|
||||
g_main_context_push_thread_default(t1_mc);
|
||||
|
||||
ml = g_main_loop_new(t1_mc, FALSE);
|
||||
|
||||
/* attach our lws activities to the main loop of this thread */
|
||||
|
||||
lws_set_log_level(LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE, NULL);
|
||||
memset(&info, 0, sizeof info);
|
||||
info.port = CONTEXT_PORT_NO_LISTEN;
|
||||
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT |
|
||||
LWS_SERVER_OPTION_GLIB;
|
||||
info.protocols = protocols;
|
||||
foreign_loops[0] = (void *)ml;
|
||||
info.foreign_loops = foreign_loops;
|
||||
info.register_notifier_list = na;
|
||||
|
||||
#if defined(LWS_WITH_MBEDTLS)
|
||||
/*
|
||||
* OpenSSL uses the system trust store. mbedTLS has to be told which
|
||||
* CA to trust explicitly.
|
||||
*/
|
||||
info.client_ssl_ca_filepath = "./warmcat.com.cer";
|
||||
#endif
|
||||
|
||||
context = lws_create_context(&info);
|
||||
if (!context) {
|
||||
lwsl_err("lws init failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* We created the lws_context and bound it to this thread's main loop,
|
||||
* let's run the thread's main loop now...
|
||||
*/
|
||||
|
||||
g_main_loop_run(ml);
|
||||
g_main_loop_unref(ml);
|
||||
|
||||
g_main_context_pop_thread_default(t1_mc);
|
||||
g_main_context_unref(t1_mc);
|
||||
|
||||
g_print("%s: ending\n", __func__);
|
||||
|
||||
lws_context_destroy(context);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
GMainContext *t1_mc = g_main_context_new();
|
||||
GtkApplication *app;
|
||||
GThread *t1;
|
||||
int status;
|
||||
|
||||
t1 = g_thread_new ("t1", t1_main, g_main_context_ref (t1_mc));
|
||||
(void)t1;
|
||||
|
||||
app = gtk_application_new("org.gtk.example", G_APPLICATION_FLAGS_NONE);
|
||||
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
|
||||
|
||||
status = g_application_run(G_APPLICATION(app), argc, argv);
|
||||
g_object_unref(app);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
58
minimal-examples/gtk/minimal-gtk/warmcat.com.cer
Normal file
58
minimal-examples/gtk/minimal-gtk/warmcat.com.cer
Normal file
|
@ -0,0 +1,58 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIFUDCCBDigAwIBAgISA4mJfIm3iCGbU9+o8YQa+4nUMA0GCSqGSIb3DQEBCwUA
|
||||
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
|
||||
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xOTA5MDcwNzA5MjNaFw0x
|
||||
OTEyMDYwNzA5MjNaMBYxFDASBgNVBAMTC3dhcm1jYXQuY29tMIIBIjANBgkqhkiG
|
||||
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwnEoH9JW3GvpadpxHGZPb5wv1Q6KfAIMWtdq
|
||||
YCOfotFxaYULuzHVxmrTTgmEqJr+eBqUBkXKmGuRR/9UipOmTu5j02qFyWHotFdF
|
||||
ZGyp//8z+Rle9Qt1nL68oNIZLDtWkybh5x00b1uo4eyEszXUaa0aLqKP3lH7Q4jI
|
||||
aSVARZ8snrJR640Gp3ByudvNTYkGz469bpWzRC/8wSNtzzY02DvHs1GxQx9tMXw+
|
||||
BbtUxeP7lpYFKEFBjgZaIKLv+4g8ItJIuO7gMSzG2JfpQHxdhrlhxpx7dsaMUcyM
|
||||
nnYXysNL5JG3KEMhkxbtdpCaEQ8jLSPbl/rnF/+mgce+lSjMuQIDAQABo4ICYjCC
|
||||
Al4wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD
|
||||
AjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSI9ai12zLFeNTEDHKI9Ghkqcpa2TAf
|
||||
BgNVHSMEGDAWgBSoSmpjBH3duubRObemRWXv86jsoTBvBggrBgEFBQcBAQRjMGEw
|
||||
LgYIKwYBBQUHMAGGImh0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlwdC5vcmcw
|
||||
LwYIKwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5vcmcv
|
||||
MBYGA1UdEQQPMA2CC3dhcm1jYXQuY29tMEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcG
|
||||
CysGAQQBgt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5
|
||||
cHQub3JnMIIBBgYKKwYBBAHWeQIEAgSB9wSB9ADyAHcAY/Lbzeg7zCzPC3KEJ1dr
|
||||
M6SNYXePvXWmOLHHaFRL2I0AAAFtCsVHHAAABAMASDBGAiEAy0q1cR4VwPL3iviL
|
||||
cBWN67kjJRXk+DwhodmeoM3kb3gCIQC2soAHFs0Umo+0RNdFrL41+hMuidh2cXbb
|
||||
Ovc6nh5tOQB3AOJpS64m6OlACeiGG7Y7g9Q+5/50iPukjyiTAZ3d8dv+AAABbQrF
|
||||
R48AAAQDAEgwRgIhANqKQm4t9by263CJ7/DLOaZCjtcK29KgJjPwhv08UMn1AiEA
|
||||
h35nGTASR8/E7xz+56ZUleqD7U1ABFgWZRZskIzsFO8wDQYJKoZIhvcNAQELBQAD
|
||||
ggEBADDJBVbKe2LPHmi8k2vxErB3Y0Ty+3gwgPEXKYtEvQ7tos89eE+QmOXAzH5J
|
||||
GwRarFf7kzmKeJv04tMebiEtshpap47oJfxCxfrtpja8hP8Cdu/v/Ae6eEzu3yet
|
||||
0N08GJdxQKfgCFaoGUptbaF2RCIZS12SVcX4TPpdP+xaiZdmIx4dGM6tReQ8+y8B
|
||||
10b4Hi2+d/zW0W1z6+FAemU6yleWriJDUik5oas9XZF5LAAMDb/WgF5eIB6P9CUG
|
||||
LuAO8lWlk9nBgXvMLTxZ74SJb17H4kFEIrIjvABNshz5gBW8xw9nfr5YIfANtwEj
|
||||
BDsq06Df3UORYVs/j3T97gPAEZ4=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
|
||||
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
|
||||
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
|
||||
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
|
||||
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
|
||||
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
|
||||
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
|
||||
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
|
||||
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
|
||||
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
|
||||
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
|
||||
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
|
||||
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
|
||||
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
|
||||
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
|
||||
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
|
||||
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
|
||||
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
|
||||
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
|
||||
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
|
||||
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
|
||||
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
|
||||
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
|
||||
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
|
||||
-----END CERTIFICATE-----
|
|
@ -342,7 +342,10 @@ int main(int argc, const char **argv)
|
|||
if (lws_cmdline_option(argc, argv, "--ev"))
|
||||
info.options |= LWS_SERVER_OPTION_LIBEV;
|
||||
else
|
||||
signal(SIGINT, sigint_handler);
|
||||
if (lws_cmdline_option(argc, argv, "--glib"))
|
||||
info.options |= LWS_SERVER_OPTION_GLIB;
|
||||
else
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
staggered = !!lws_cmdline_option(argc, argv, "-s");
|
||||
if ((p = lws_cmdline_option(argc, argv, "-d")))
|
||||
|
|
|
@ -170,7 +170,10 @@ int main(int argc, const char **argv)
|
|||
if (lws_cmdline_option(argc, argv, "--ev"))
|
||||
info.options |= LWS_SERVER_OPTION_LIBEV;
|
||||
else
|
||||
signal(SIGINT, sigint_handler);
|
||||
if (lws_cmdline_option(argc, argv, "--glib"))
|
||||
info.options |= LWS_SERVER_OPTION_GLIB;
|
||||
else
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
context = lws_create_context(&info);
|
||||
if (!context) {
|
||||
|
|
|
@ -5,6 +5,7 @@ include(CheckCSourceCompiles)
|
|||
set(SAMP lws-minimal-http-server-eventlib-foreign)
|
||||
set(SRCS minimal-http-server-eventlib-foreign.c)
|
||||
|
||||
|
||||
# If we are being built as part of lws, confirm current build config supports
|
||||
# reqconfig, else skip building ourselves.
|
||||
#
|
||||
|
@ -66,9 +67,13 @@ set(requirements 1)
|
|||
require_lws_config(LWS_ROLE_H1 1 requirements)
|
||||
require_lws_config(LWS_WITH_SERVER 1 requirements)
|
||||
|
||||
|
||||
|
||||
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(LWS_WITH_LIBUV)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_LIBUV)
|
||||
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(LWS_WITH_LIBEVENT)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_LIBEVENT)
|
||||
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(LWS_WITH_LIBEV)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_LIBEV)
|
||||
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(LWS_WITH_GLIB)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_GLIB)
|
||||
|
||||
|
||||
if (LWS_WITH_LIBUV)
|
||||
set(extralibs ${extralibs} uv)
|
||||
|
@ -79,10 +84,33 @@ endif()
|
|||
if (LWS_WITH_LIBEV)
|
||||
set(extralibs ${extralibs} ev)
|
||||
endif()
|
||||
if (LWS_WITH_GLIB)
|
||||
set(LWS_GLIB_INCLUDE_DIRS CACHE PATH "Path to the glib include directory")
|
||||
set(LWS_GLIB_LIBRARIES CACHE PATH "Path to the glib library")
|
||||
include (FindPkgConfig)
|
||||
if (NOT GLIB_FOUND)
|
||||
find_path(GLIB_INCLUDE_DIRS NAMES glib-2.0/glib.h)
|
||||
find_library(GLIB_LIBRARIES NAMES glib-2.0)
|
||||
if(GLIB_INCLUDE_DIRS AND GLIB_LIBRARIES)
|
||||
set(GLIB_FOUND 1)
|
||||
endif()
|
||||
if (GLIB_INCLUDE_DIRS)
|
||||
set(GLIB_INCLUDE_DIRS "${GLIB_INCLUDE_DIRS}/glib-2.0")
|
||||
endif()
|
||||
endif()
|
||||
PKG_SEARCH_MODULE(LWS_GLIB2 glib-2.0)
|
||||
if (LWS_GLIB2_FOUND)
|
||||
list(APPEND GLIB_INCLUDE_DIRS "${LWS_GLIB2_INCLUDE_DIRS}")
|
||||
endif()
|
||||
message("glib include dir: ${GLIB_INCLUDE_DIRS}")
|
||||
message("glib libraries: ${GLIB_LIBRARIES}")
|
||||
include_directories("${GLIB_INCLUDE_DIRS}")
|
||||
set(extralibs ${extralibs} ${GLIB_LIBRARIES})
|
||||
endif()
|
||||
|
||||
message("Extra libs: ${extralibs}")
|
||||
|
||||
if (NOT LWS_WITH_LIBUV AND NOT LWS_WITH_LIBEVENT AND NOT LWS_WITH_LIBEV)
|
||||
if (NOT LWS_WITH_LIBUV AND NOT LWS_WITH_LIBEVENT AND NOT LWS_WITH_LIBEV AND NOT LWS_WITH_GLIB)
|
||||
set(requirements 0)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* lws-minimal-http-server-eventlib-foreign
|
||||
*
|
||||
* Written in 2010-2019 by Andy Green <andy@warmcat.com>
|
||||
* 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.
|
||||
|
@ -205,6 +205,59 @@ foreign_event_loop_cleanup_libevent(void)
|
|||
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_GLIB)
|
||||
|
||||
#include <glib-2.0/glib.h>
|
||||
#include <glib-unix.h>
|
||||
|
||||
static GMainLoop *loop_glib;
|
||||
static guint timer_outer_glib;
|
||||
static guint 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 = g_unix_signal_add(SIGINT,
|
||||
G_SOURCE_FUNC(signal_cb_glib), NULL);
|
||||
|
||||
timer_outer_glib = g_timeout_add(1000, timer_cb_glib, NULL);
|
||||
|
||||
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 */
|
||||
g_source_remove(sighandler_glib);
|
||||
g_main_loop_unref(loop_glib);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_LIBEV)
|
||||
|
||||
static struct ev_loop *loop_ev;
|
||||
|
@ -315,6 +368,10 @@ foreign_timer_service(void *foreign_loop)
|
|||
#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
|
||||
break;
|
||||
default:
|
||||
|
@ -368,9 +425,12 @@ int main(int argc, const char **argv)
|
|||
else
|
||||
if (lws_cmdline_option(argc, argv, "--ev"))
|
||||
info.options |= LWS_SERVER_OPTION_LIBEV;
|
||||
else {
|
||||
else
|
||||
if (lws_cmdline_option(argc, argv, "--glib"))
|
||||
info.options |= LWS_SERVER_OPTION_GLIB;
|
||||
else {
|
||||
lwsl_err("This app only makes sense when used\n");
|
||||
lwsl_err(" with a foreign loop, --uv, --event, or --ev\n");
|
||||
lwsl_err(" with a foreign loop, --uv, --event, --glib, or --ev\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -401,6 +461,10 @@ int main(int argc, const char **argv)
|
|||
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
|
||||
|
||||
lws_context_destroy(context);
|
||||
|
||||
|
@ -418,6 +482,10 @@ int main(int argc, const char **argv)
|
|||
if (info.options & LWS_SERVER_OPTION_LIBEV)
|
||||
foreign_event_loop_cleanup_libev();
|
||||
#endif
|
||||
#if defined(LWS_WITH_LIBEV)
|
||||
if (info.options & LWS_SERVER_OPTION_GLIB)
|
||||
foreign_event_loop_cleanup_glib();
|
||||
#endif
|
||||
|
||||
lwsl_user("%s: exiting...\n", __func__);
|
||||
|
||||
|
|
|
@ -130,7 +130,10 @@ int main(int argc, const char **argv)
|
|||
if (lws_cmdline_option(argc, argv, "--ev"))
|
||||
info.options |= LWS_SERVER_OPTION_LIBEV;
|
||||
else
|
||||
signal(SIGINT, sigint_handler);
|
||||
if (lws_cmdline_option(argc, argv, "--glib"))
|
||||
info.options |= LWS_SERVER_OPTION_GLIB;
|
||||
else
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
context = lws_create_context(&info);
|
||||
if (!context) {
|
||||
|
|
|
@ -101,7 +101,10 @@ int main(int argc, const char **argv)
|
|||
if (lws_cmdline_option(argc, argv, "--ev"))
|
||||
info.options |= LWS_SERVER_OPTION_LIBEV;
|
||||
else
|
||||
signal(SIGINT, sigint_handler);
|
||||
if (lws_cmdline_option(argc, argv, "--glib"))
|
||||
info.options |= LWS_SERVER_OPTION_GLIB;
|
||||
else
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
context = lws_create_context(&info);
|
||||
if (!context) {
|
||||
|
|
Loading…
Add table
Reference in a new issue