1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci */ 24d4afb5ceSopenharmony_ci 25d4afb5ceSopenharmony_ci#include "private-lib-core.h" 26d4afb5ceSopenharmony_ci 27d4afb5ceSopenharmony_ci#include <glib-unix.h> 28d4afb5ceSopenharmony_ci 29d4afb5ceSopenharmony_ci#include "private-lib-event-libs-glib.h" 30d4afb5ceSopenharmony_ci 31d4afb5ceSopenharmony_ci#if !defined(G_SOURCE_FUNC) 32d4afb5ceSopenharmony_ci#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f)) 33d4afb5ceSopenharmony_ci#endif 34d4afb5ceSopenharmony_ci 35d4afb5ceSopenharmony_ci#define pt_to_priv_glib(_pt) ((struct lws_pt_eventlibs_glib *)(_pt)->evlib_pt) 36d4afb5ceSopenharmony_ci#define wsi_to_priv_glib(_w) ((struct lws_wsi_eventlibs_glib *)(_w)->evlib_wsi) 37d4afb5ceSopenharmony_ci 38d4afb5ceSopenharmony_ci#define wsi_to_subclass(_w) (wsi_to_priv_glib(_w)->w_read.source) 39d4afb5ceSopenharmony_ci#define wsi_to_gsource(_w) ((GSource *)wsi_to_subclass(_w)) 40d4afb5ceSopenharmony_ci#define pt_to_loop(_pt) (pt_to_priv_glib(_pt)->loop) 41d4afb5ceSopenharmony_ci#define pt_to_g_main_context(_pt) g_main_loop_get_context(pt_to_loop(_pt)) 42d4afb5ceSopenharmony_ci 43d4afb5ceSopenharmony_ci#define lws_gs_valid(t) (t.gs) 44d4afb5ceSopenharmony_ci#define lws_gs_destroy(t) if (lws_gs_valid(t)) { \ 45d4afb5ceSopenharmony_ci g_source_destroy(t.gs); \ 46d4afb5ceSopenharmony_ci g_source_unref(t.gs); \ 47d4afb5ceSopenharmony_ci t.gs = NULL; t.tag = 0; } 48d4afb5ceSopenharmony_ci 49d4afb5ceSopenharmony_cistatic gboolean 50d4afb5ceSopenharmony_cilws_glib_idle_timer_cb(void *p); 51d4afb5ceSopenharmony_ci 52d4afb5ceSopenharmony_cistatic gboolean 53d4afb5ceSopenharmony_cilws_glib_hrtimer_cb(void *p); 54d4afb5ceSopenharmony_ci 55d4afb5ceSopenharmony_cistatic gboolean 56d4afb5ceSopenharmony_cilws_glib_check(GSource *src) 57d4afb5ceSopenharmony_ci{ 58d4afb5ceSopenharmony_ci struct lws_io_watcher_glib_subclass *sub = 59d4afb5ceSopenharmony_ci (struct lws_io_watcher_glib_subclass *)src; 60d4afb5ceSopenharmony_ci 61d4afb5ceSopenharmony_ci return !!g_source_query_unix_fd(src, sub->tag); 62d4afb5ceSopenharmony_ci} 63d4afb5ceSopenharmony_ci 64d4afb5ceSopenharmony_ci/* 65d4afb5ceSopenharmony_ci * These helpers attach only to the main_context that belongs to the pt's glib 66d4afb5ceSopenharmony_ci * mainloop. The simpler g_timeout_add() and g_idle_add() are forbidden 67d4afb5ceSopenharmony_ci * because they implicitly choose the default main context to attach to 68d4afb5ceSopenharmony_ci * instead of specifically the loop bound to the pt. 69d4afb5ceSopenharmony_ci * 70d4afb5ceSopenharmony_ci * https://developer.gnome.org/programming-guidelines/unstable/main-contexts.html.en#what-is-gmaincontext 71d4afb5ceSopenharmony_ci */ 72d4afb5ceSopenharmony_ci 73d4afb5ceSopenharmony_cistatic int 74d4afb5ceSopenharmony_cilws_glib_set_idle(struct lws_context_per_thread *pt) 75d4afb5ceSopenharmony_ci{ 76d4afb5ceSopenharmony_ci if (lws_gs_valid(pt_to_priv_glib(pt)->idle)) 77d4afb5ceSopenharmony_ci return 0; 78d4afb5ceSopenharmony_ci 79d4afb5ceSopenharmony_ci pt_to_priv_glib(pt)->idle.gs = g_idle_source_new(); 80d4afb5ceSopenharmony_ci if (!pt_to_priv_glib(pt)->idle.gs) 81d4afb5ceSopenharmony_ci return 1; 82d4afb5ceSopenharmony_ci 83d4afb5ceSopenharmony_ci g_source_set_callback(pt_to_priv_glib(pt)->idle.gs, 84d4afb5ceSopenharmony_ci lws_glib_idle_timer_cb, pt, NULL); 85d4afb5ceSopenharmony_ci pt_to_priv_glib(pt)->idle.tag = g_source_attach( 86d4afb5ceSopenharmony_ci pt_to_priv_glib(pt)->idle.gs, pt_to_g_main_context(pt)); 87d4afb5ceSopenharmony_ci 88d4afb5ceSopenharmony_ci return 0; 89d4afb5ceSopenharmony_ci} 90d4afb5ceSopenharmony_ci 91d4afb5ceSopenharmony_cistatic int 92d4afb5ceSopenharmony_cilws_glib_set_timeout(struct lws_context_per_thread *pt, unsigned int ms) 93d4afb5ceSopenharmony_ci{ 94d4afb5ceSopenharmony_ci lws_gs_destroy(pt_to_priv_glib(pt)->hrtimer); 95d4afb5ceSopenharmony_ci 96d4afb5ceSopenharmony_ci pt_to_priv_glib(pt)->hrtimer.gs = g_timeout_source_new(ms); 97d4afb5ceSopenharmony_ci if (!pt_to_priv_glib(pt)->hrtimer.gs) 98d4afb5ceSopenharmony_ci return 1; 99d4afb5ceSopenharmony_ci 100d4afb5ceSopenharmony_ci g_source_set_callback(pt_to_priv_glib(pt)->hrtimer.gs, 101d4afb5ceSopenharmony_ci lws_glib_hrtimer_cb, pt, NULL); 102d4afb5ceSopenharmony_ci pt_to_priv_glib(pt)->hrtimer.tag = g_source_attach( 103d4afb5ceSopenharmony_ci pt_to_priv_glib(pt)->hrtimer.gs, 104d4afb5ceSopenharmony_ci pt_to_g_main_context(pt)); 105d4afb5ceSopenharmony_ci 106d4afb5ceSopenharmony_ci return 0; 107d4afb5ceSopenharmony_ci} 108d4afb5ceSopenharmony_ci 109d4afb5ceSopenharmony_cistatic gboolean 110d4afb5ceSopenharmony_cilws_glib_dispatch(GSource *src, GSourceFunc x, gpointer userData) 111d4afb5ceSopenharmony_ci{ 112d4afb5ceSopenharmony_ci struct lws_io_watcher_glib_subclass *sub = 113d4afb5ceSopenharmony_ci (struct lws_io_watcher_glib_subclass *)src; 114d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt; 115d4afb5ceSopenharmony_ci struct lws_pollfd eventfd; 116d4afb5ceSopenharmony_ci GIOCondition cond; 117d4afb5ceSopenharmony_ci 118d4afb5ceSopenharmony_ci cond = g_source_query_unix_fd(src, sub->tag); 119d4afb5ceSopenharmony_ci eventfd.revents = (short)cond; 120d4afb5ceSopenharmony_ci 121d4afb5ceSopenharmony_ci /* translate from glib event namespace to platform */ 122d4afb5ceSopenharmony_ci 123d4afb5ceSopenharmony_ci if (cond & G_IO_IN) 124d4afb5ceSopenharmony_ci eventfd.revents |= LWS_POLLIN; 125d4afb5ceSopenharmony_ci if (cond & G_IO_OUT) 126d4afb5ceSopenharmony_ci eventfd.revents |= LWS_POLLOUT; 127d4afb5ceSopenharmony_ci if (cond & G_IO_ERR) 128d4afb5ceSopenharmony_ci eventfd.revents |= LWS_POLLHUP; 129d4afb5ceSopenharmony_ci if (cond & G_IO_HUP) 130d4afb5ceSopenharmony_ci eventfd.revents |= LWS_POLLHUP; 131d4afb5ceSopenharmony_ci 132d4afb5ceSopenharmony_ci eventfd.events = eventfd.revents; 133d4afb5ceSopenharmony_ci eventfd.fd = sub->wsi->desc.sockfd; 134d4afb5ceSopenharmony_ci 135d4afb5ceSopenharmony_ci lwsl_wsi_debug(sub->wsi, "fd %d, events %d", 136d4afb5ceSopenharmony_ci eventfd.fd, eventfd.revents); 137d4afb5ceSopenharmony_ci 138d4afb5ceSopenharmony_ci pt = &sub->wsi->a.context->pt[(int)sub->wsi->tsi]; 139d4afb5ceSopenharmony_ci if (pt->is_destroyed) 140d4afb5ceSopenharmony_ci return G_SOURCE_CONTINUE; 141d4afb5ceSopenharmony_ci 142d4afb5ceSopenharmony_ci lws_service_fd_tsi(sub->wsi->a.context, &eventfd, sub->wsi->tsi); 143d4afb5ceSopenharmony_ci 144d4afb5ceSopenharmony_ci if (!lws_gs_valid(pt_to_priv_glib(pt)->idle)) 145d4afb5ceSopenharmony_ci lws_glib_set_idle(pt); 146d4afb5ceSopenharmony_ci 147d4afb5ceSopenharmony_ci if (pt->destroy_self) 148d4afb5ceSopenharmony_ci lws_context_destroy(pt->context); 149d4afb5ceSopenharmony_ci 150d4afb5ceSopenharmony_ci return G_SOURCE_CONTINUE; 151d4afb5ceSopenharmony_ci} 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_cistatic const GSourceFuncs lws_glib_source_ops = { 154d4afb5ceSopenharmony_ci .prepare = NULL, 155d4afb5ceSopenharmony_ci .check = lws_glib_check, 156d4afb5ceSopenharmony_ci .dispatch = lws_glib_dispatch, 157d4afb5ceSopenharmony_ci .finalize = NULL, 158d4afb5ceSopenharmony_ci}; 159d4afb5ceSopenharmony_ci 160d4afb5ceSopenharmony_ci/* 161d4afb5ceSopenharmony_ci * This is the callback for a timer object that is set to the earliest scheduled 162d4afb5ceSopenharmony_ci * lws event... it services any lws scheduled events that are ready, and then 163d4afb5ceSopenharmony_ci * resets the event loop timer to the earliest remaining event, if any. 164d4afb5ceSopenharmony_ci */ 165d4afb5ceSopenharmony_ci 166d4afb5ceSopenharmony_cistatic gboolean 167d4afb5ceSopenharmony_cilws_glib_hrtimer_cb(void *p) 168d4afb5ceSopenharmony_ci{ 169d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = (struct lws_context_per_thread *)p; 170d4afb5ceSopenharmony_ci unsigned int ms; 171d4afb5ceSopenharmony_ci lws_usec_t us; 172d4afb5ceSopenharmony_ci 173d4afb5ceSopenharmony_ci lws_pt_lock(pt, __func__); 174d4afb5ceSopenharmony_ci 175d4afb5ceSopenharmony_ci lws_gs_destroy(pt_to_priv_glib(pt)->hrtimer); 176d4afb5ceSopenharmony_ci 177d4afb5ceSopenharmony_ci us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, 178d4afb5ceSopenharmony_ci lws_now_usecs()); 179d4afb5ceSopenharmony_ci if (us) { 180d4afb5ceSopenharmony_ci ms = (unsigned int)(us / LWS_US_PER_MS); 181d4afb5ceSopenharmony_ci if (!ms) 182d4afb5ceSopenharmony_ci ms = 1; 183d4afb5ceSopenharmony_ci 184d4afb5ceSopenharmony_ci lws_glib_set_timeout(pt, ms); 185d4afb5ceSopenharmony_ci } 186d4afb5ceSopenharmony_ci 187d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 188d4afb5ceSopenharmony_ci 189d4afb5ceSopenharmony_ci lws_glib_set_idle(pt); 190d4afb5ceSopenharmony_ci 191d4afb5ceSopenharmony_ci return FALSE; /* stop it repeating */ 192d4afb5ceSopenharmony_ci} 193d4afb5ceSopenharmony_ci 194d4afb5ceSopenharmony_cistatic gboolean 195d4afb5ceSopenharmony_cilws_glib_idle_timer_cb(void *p) 196d4afb5ceSopenharmony_ci{ 197d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = (struct lws_context_per_thread *)p; 198d4afb5ceSopenharmony_ci 199d4afb5ceSopenharmony_ci if (pt->is_destroyed) 200d4afb5ceSopenharmony_ci return FALSE; 201d4afb5ceSopenharmony_ci 202d4afb5ceSopenharmony_ci lws_service_do_ripe_rxflow(pt); 203d4afb5ceSopenharmony_ci lws_glib_hrtimer_cb(pt); 204d4afb5ceSopenharmony_ci 205d4afb5ceSopenharmony_ci /* 206d4afb5ceSopenharmony_ci * is there anybody with pending stuff that needs service forcing? 207d4afb5ceSopenharmony_ci */ 208d4afb5ceSopenharmony_ci if (!lws_service_adjust_timeout(pt->context, 1, pt->tid)) { 209d4afb5ceSopenharmony_ci /* -1 timeout means just do forced service */ 210d4afb5ceSopenharmony_ci _lws_plat_service_forced_tsi(pt->context, pt->tid); 211d4afb5ceSopenharmony_ci /* still somebody left who wants forced service? */ 212d4afb5ceSopenharmony_ci if (!lws_service_adjust_timeout(pt->context, 1, pt->tid)) 213d4afb5ceSopenharmony_ci return TRUE; 214d4afb5ceSopenharmony_ci } 215d4afb5ceSopenharmony_ci 216d4afb5ceSopenharmony_ci if (pt->destroy_self) 217d4afb5ceSopenharmony_ci lws_context_destroy(pt->context); 218d4afb5ceSopenharmony_ci 219d4afb5ceSopenharmony_ci /* 220d4afb5ceSopenharmony_ci * For glib, this disables the idle callback. Otherwise we keep 221d4afb5ceSopenharmony_ci * coming back here immediately endlessly. 222d4afb5ceSopenharmony_ci * 223d4afb5ceSopenharmony_ci * We reenable the idle callback on the next network or scheduled event 224d4afb5ceSopenharmony_ci */ 225d4afb5ceSopenharmony_ci 226d4afb5ceSopenharmony_ci lws_gs_destroy(pt_to_priv_glib(pt)->idle); 227d4afb5ceSopenharmony_ci 228d4afb5ceSopenharmony_ci return FALSE; 229d4afb5ceSopenharmony_ci} 230d4afb5ceSopenharmony_ci 231d4afb5ceSopenharmony_civoid 232d4afb5ceSopenharmony_cilws_glib_sigint_cb(void *ctx) 233d4afb5ceSopenharmony_ci{ 234d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = ctx; 235d4afb5ceSopenharmony_ci 236d4afb5ceSopenharmony_ci pt->inside_service = 1; 237d4afb5ceSopenharmony_ci 238d4afb5ceSopenharmony_ci if (pt->context->eventlib_signal_cb) { 239d4afb5ceSopenharmony_ci pt->context->eventlib_signal_cb(NULL, 0); 240d4afb5ceSopenharmony_ci 241d4afb5ceSopenharmony_ci return; 242d4afb5ceSopenharmony_ci } 243d4afb5ceSopenharmony_ci if (!pt->event_loop_foreign) 244d4afb5ceSopenharmony_ci g_main_loop_quit(pt_to_loop(pt)); 245d4afb5ceSopenharmony_ci} 246d4afb5ceSopenharmony_ci 247d4afb5ceSopenharmony_cistatic int 248d4afb5ceSopenharmony_cielops_init_context_glib(struct lws_context *context, 249d4afb5ceSopenharmony_ci const struct lws_context_creation_info *info) 250d4afb5ceSopenharmony_ci{ 251d4afb5ceSopenharmony_ci// int n; 252d4afb5ceSopenharmony_ci 253d4afb5ceSopenharmony_ci context->eventlib_signal_cb = info->signal_cb; 254d4afb5ceSopenharmony_ci 255d4afb5ceSopenharmony_ci// for (n = 0; n < context->count_threads; n++) 256d4afb5ceSopenharmony_ci// pt_to_priv_glib(&context->pt[n])->w_sigint.context = context; 257d4afb5ceSopenharmony_ci 258d4afb5ceSopenharmony_ci return 0; 259d4afb5ceSopenharmony_ci} 260d4afb5ceSopenharmony_ci 261d4afb5ceSopenharmony_cistatic int 262d4afb5ceSopenharmony_cielops_accept_glib(struct lws *wsi) 263d4afb5ceSopenharmony_ci{ 264d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 265d4afb5ceSopenharmony_ci struct lws_wsi_eventlibs_glib *wsipr = wsi_to_priv_glib(wsi); 266d4afb5ceSopenharmony_ci int fd; 267d4afb5ceSopenharmony_ci 268d4afb5ceSopenharmony_ci assert(!wsi_to_subclass(wsi)); 269d4afb5ceSopenharmony_ci 270d4afb5ceSopenharmony_ci wsi_to_subclass(wsi) = (struct lws_io_watcher_glib_subclass *) 271d4afb5ceSopenharmony_ci g_source_new((GSourceFuncs *)&lws_glib_source_ops, 272d4afb5ceSopenharmony_ci sizeof(*wsi_to_subclass(wsi))); 273d4afb5ceSopenharmony_ci if (!wsi_to_subclass(wsi)) 274d4afb5ceSopenharmony_ci return 1; 275d4afb5ceSopenharmony_ci 276d4afb5ceSopenharmony_ci wsipr->w_read.context = wsi->a.context; 277d4afb5ceSopenharmony_ci wsi_to_subclass(wsi)->wsi = wsi; 278d4afb5ceSopenharmony_ci 279d4afb5ceSopenharmony_ci if (wsi->role_ops->file_handle) 280d4afb5ceSopenharmony_ci fd = wsi->desc.filefd; 281d4afb5ceSopenharmony_ci else 282d4afb5ceSopenharmony_ci fd = wsi->desc.sockfd; 283d4afb5ceSopenharmony_ci 284d4afb5ceSopenharmony_ci wsi_to_subclass(wsi)->tag = g_source_add_unix_fd(wsi_to_gsource(wsi), 285d4afb5ceSopenharmony_ci fd, (GIOCondition)LWS_POLLIN); 286d4afb5ceSopenharmony_ci wsipr->w_read.actual_events = LWS_POLLIN; 287d4afb5ceSopenharmony_ci 288d4afb5ceSopenharmony_ci g_source_set_callback(wsi_to_gsource(wsi), 289d4afb5ceSopenharmony_ci G_SOURCE_FUNC(lws_service_fd), wsi->a.context, NULL); 290d4afb5ceSopenharmony_ci 291d4afb5ceSopenharmony_ci g_source_attach(wsi_to_gsource(wsi), pt_to_g_main_context(pt)); 292d4afb5ceSopenharmony_ci 293d4afb5ceSopenharmony_ci return 0; 294d4afb5ceSopenharmony_ci} 295d4afb5ceSopenharmony_ci 296d4afb5ceSopenharmony_cistatic int 297d4afb5ceSopenharmony_cielops_listen_init_glib(struct lws_dll2 *d, void *user) 298d4afb5ceSopenharmony_ci{ 299d4afb5ceSopenharmony_ci struct lws *wsi = lws_container_of(d, struct lws, listen_list); 300d4afb5ceSopenharmony_ci 301d4afb5ceSopenharmony_ci elops_accept_glib(wsi); 302d4afb5ceSopenharmony_ci 303d4afb5ceSopenharmony_ci return 0; 304d4afb5ceSopenharmony_ci} 305d4afb5ceSopenharmony_ci 306d4afb5ceSopenharmony_cistatic int 307d4afb5ceSopenharmony_cielops_init_pt_glib(struct lws_context *context, void *_loop, int tsi) 308d4afb5ceSopenharmony_ci{ 309d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[tsi]; 310d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_glib *ptpr = pt_to_priv_glib(pt); 311d4afb5ceSopenharmony_ci GMainLoop *loop = (GMainLoop *)_loop; 312d4afb5ceSopenharmony_ci 313d4afb5ceSopenharmony_ci if (!loop) 314d4afb5ceSopenharmony_ci loop = g_main_loop_new(NULL, 0); 315d4afb5ceSopenharmony_ci else 316d4afb5ceSopenharmony_ci context->pt[tsi].event_loop_foreign = 1; 317d4afb5ceSopenharmony_ci 318d4afb5ceSopenharmony_ci if (!loop) { 319d4afb5ceSopenharmony_ci lwsl_cx_err(context, "creating glib loop failed"); 320d4afb5ceSopenharmony_ci 321d4afb5ceSopenharmony_ci return -1; 322d4afb5ceSopenharmony_ci } 323d4afb5ceSopenharmony_ci 324d4afb5ceSopenharmony_ci ptpr->loop = loop; 325d4afb5ceSopenharmony_ci 326d4afb5ceSopenharmony_ci lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_init_glib); 327d4afb5ceSopenharmony_ci 328d4afb5ceSopenharmony_ci lws_glib_set_idle(pt); 329d4afb5ceSopenharmony_ci 330d4afb5ceSopenharmony_ci /* Register the signal watcher unless it's a foreign loop */ 331d4afb5ceSopenharmony_ci 332d4afb5ceSopenharmony_ci if (pt->event_loop_foreign) 333d4afb5ceSopenharmony_ci return 0; 334d4afb5ceSopenharmony_ci 335d4afb5ceSopenharmony_ci ptpr->sigint.tag = g_unix_signal_add(SIGINT, 336d4afb5ceSopenharmony_ci G_SOURCE_FUNC(lws_glib_sigint_cb), pt); 337d4afb5ceSopenharmony_ci 338d4afb5ceSopenharmony_ci return 0; 339d4afb5ceSopenharmony_ci} 340d4afb5ceSopenharmony_ci 341d4afb5ceSopenharmony_ci/* 342d4afb5ceSopenharmony_ci * We are changing the event wait for this guy 343d4afb5ceSopenharmony_ci */ 344d4afb5ceSopenharmony_ci 345d4afb5ceSopenharmony_cistatic void 346d4afb5ceSopenharmony_cielops_io_glib(struct lws *wsi, unsigned int flags) 347d4afb5ceSopenharmony_ci{ 348d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 349d4afb5ceSopenharmony_ci struct lws_wsi_eventlibs_glib *wsipr = wsi_to_priv_glib(wsi); 350d4afb5ceSopenharmony_ci GIOCondition cond = wsipr->w_read.actual_events | G_IO_ERR; 351d4afb5ceSopenharmony_ci 352d4afb5ceSopenharmony_ci if (!pt_to_loop(pt) || wsi->a.context->being_destroyed || 353d4afb5ceSopenharmony_ci pt->is_destroyed) 354d4afb5ceSopenharmony_ci return; 355d4afb5ceSopenharmony_ci 356d4afb5ceSopenharmony_ci if (!wsi_to_subclass(wsi)) 357d4afb5ceSopenharmony_ci return; 358d4afb5ceSopenharmony_ci 359d4afb5ceSopenharmony_ci /* 360d4afb5ceSopenharmony_ci * We are being given individual set / clear operations using 361d4afb5ceSopenharmony_ci * LWS_EV_ common namespace, convert them to glib namespace bitfield 362d4afb5ceSopenharmony_ci */ 363d4afb5ceSopenharmony_ci 364d4afb5ceSopenharmony_ci if (flags & LWS_EV_READ) { 365d4afb5ceSopenharmony_ci if (flags & LWS_EV_STOP) 366d4afb5ceSopenharmony_ci cond &= (unsigned int)~(G_IO_IN | G_IO_HUP); 367d4afb5ceSopenharmony_ci else 368d4afb5ceSopenharmony_ci cond |= G_IO_IN | G_IO_HUP; 369d4afb5ceSopenharmony_ci } 370d4afb5ceSopenharmony_ci 371d4afb5ceSopenharmony_ci if (flags & LWS_EV_WRITE) { 372d4afb5ceSopenharmony_ci if (flags & LWS_EV_STOP) 373d4afb5ceSopenharmony_ci cond &= (unsigned int)~G_IO_OUT; 374d4afb5ceSopenharmony_ci else 375d4afb5ceSopenharmony_ci cond |= G_IO_OUT; 376d4afb5ceSopenharmony_ci } 377d4afb5ceSopenharmony_ci 378d4afb5ceSopenharmony_ci wsipr->w_read.actual_events = (uint8_t)cond; 379d4afb5ceSopenharmony_ci 380d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "fd %d, 0x%x/0x%x", wsi->desc.sockfd, 381d4afb5ceSopenharmony_ci flags, (int)cond); 382d4afb5ceSopenharmony_ci 383d4afb5ceSopenharmony_ci g_source_modify_unix_fd(wsi_to_gsource(wsi), wsi_to_subclass(wsi)->tag, 384d4afb5ceSopenharmony_ci cond); 385d4afb5ceSopenharmony_ci} 386d4afb5ceSopenharmony_ci 387d4afb5ceSopenharmony_cistatic void 388d4afb5ceSopenharmony_cielops_run_pt_glib(struct lws_context *context, int tsi) 389d4afb5ceSopenharmony_ci{ 390d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[tsi]; 391d4afb5ceSopenharmony_ci 392d4afb5ceSopenharmony_ci if (pt_to_loop(pt)) 393d4afb5ceSopenharmony_ci g_main_loop_run(pt_to_loop(pt)); 394d4afb5ceSopenharmony_ci} 395d4afb5ceSopenharmony_ci 396d4afb5ceSopenharmony_cistatic void 397d4afb5ceSopenharmony_cielops_destroy_wsi_glib(struct lws *wsi) 398d4afb5ceSopenharmony_ci{ 399d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt; 400d4afb5ceSopenharmony_ci 401d4afb5ceSopenharmony_ci if (!wsi) 402d4afb5ceSopenharmony_ci return; 403d4afb5ceSopenharmony_ci 404d4afb5ceSopenharmony_ci pt = &wsi->a.context->pt[(int)wsi->tsi]; 405d4afb5ceSopenharmony_ci if (pt->is_destroyed) 406d4afb5ceSopenharmony_ci return; 407d4afb5ceSopenharmony_ci 408d4afb5ceSopenharmony_ci if (!wsi_to_gsource(wsi)) 409d4afb5ceSopenharmony_ci return; 410d4afb5ceSopenharmony_ci 411d4afb5ceSopenharmony_ci if (wsi_to_subclass(wsi)->tag) { 412d4afb5ceSopenharmony_ci g_source_remove_unix_fd(wsi_to_gsource(wsi), 413d4afb5ceSopenharmony_ci wsi_to_subclass(wsi)->tag); 414d4afb5ceSopenharmony_ci wsi_to_subclass(wsi)->tag = NULL; 415d4afb5ceSopenharmony_ci } 416d4afb5ceSopenharmony_ci 417d4afb5ceSopenharmony_ci g_source_destroy(wsi_to_gsource(wsi)); 418d4afb5ceSopenharmony_ci g_source_unref(wsi_to_gsource(wsi)); 419d4afb5ceSopenharmony_ci wsi_to_subclass(wsi) = NULL; 420d4afb5ceSopenharmony_ci} 421d4afb5ceSopenharmony_ci 422d4afb5ceSopenharmony_cistatic int 423d4afb5ceSopenharmony_cielops_listen_destroy_glib(struct lws_dll2 *d, void *user) 424d4afb5ceSopenharmony_ci{ 425d4afb5ceSopenharmony_ci struct lws *wsi = lws_container_of(d, struct lws, listen_list); 426d4afb5ceSopenharmony_ci 427d4afb5ceSopenharmony_ci elops_destroy_wsi_glib(wsi); 428d4afb5ceSopenharmony_ci 429d4afb5ceSopenharmony_ci return 0; 430d4afb5ceSopenharmony_ci} 431d4afb5ceSopenharmony_ci 432d4afb5ceSopenharmony_cistatic void 433d4afb5ceSopenharmony_cielops_destroy_pt_glib(struct lws_context *context, int tsi) 434d4afb5ceSopenharmony_ci{ 435d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[tsi]; 436d4afb5ceSopenharmony_ci struct lws_pt_eventlibs_glib *ptpr = pt_to_priv_glib(pt); 437d4afb5ceSopenharmony_ci 438d4afb5ceSopenharmony_ci if (!pt_to_loop(pt)) 439d4afb5ceSopenharmony_ci return; 440d4afb5ceSopenharmony_ci 441d4afb5ceSopenharmony_ci lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_destroy_glib); 442d4afb5ceSopenharmony_ci 443d4afb5ceSopenharmony_ci lws_gs_destroy(ptpr->idle); 444d4afb5ceSopenharmony_ci lws_gs_destroy(ptpr->hrtimer); 445d4afb5ceSopenharmony_ci 446d4afb5ceSopenharmony_ci if (!pt->event_loop_foreign) { 447d4afb5ceSopenharmony_ci g_main_loop_quit(pt_to_loop(pt)); 448d4afb5ceSopenharmony_ci lws_gs_destroy(ptpr->sigint); 449d4afb5ceSopenharmony_ci g_main_loop_unref(pt_to_loop(pt)); 450d4afb5ceSopenharmony_ci } 451d4afb5ceSopenharmony_ci 452d4afb5ceSopenharmony_ci pt_to_loop(pt) = NULL; 453d4afb5ceSopenharmony_ci} 454d4afb5ceSopenharmony_ci 455d4afb5ceSopenharmony_cistatic int 456d4afb5ceSopenharmony_cielops_destroy_context2_glib(struct lws_context *context) 457d4afb5ceSopenharmony_ci{ 458d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[0]; 459d4afb5ceSopenharmony_ci int n; 460d4afb5ceSopenharmony_ci 461d4afb5ceSopenharmony_ci for (n = 0; n < (int)context->count_threads; n++) { 462d4afb5ceSopenharmony_ci if (!pt->event_loop_foreign) 463d4afb5ceSopenharmony_ci g_main_loop_quit(pt_to_loop(pt)); 464d4afb5ceSopenharmony_ci pt++; 465d4afb5ceSopenharmony_ci } 466d4afb5ceSopenharmony_ci 467d4afb5ceSopenharmony_ci return 0; 468d4afb5ceSopenharmony_ci} 469d4afb5ceSopenharmony_ci 470d4afb5ceSopenharmony_cistatic int 471d4afb5ceSopenharmony_cielops_wsi_logical_close_glib(struct lws *wsi) 472d4afb5ceSopenharmony_ci{ 473d4afb5ceSopenharmony_ci elops_destroy_wsi_glib(wsi); 474d4afb5ceSopenharmony_ci 475d4afb5ceSopenharmony_ci return 0; 476d4afb5ceSopenharmony_ci} 477d4afb5ceSopenharmony_ci 478d4afb5ceSopenharmony_cistatic const struct lws_event_loop_ops event_loop_ops_glib = { 479d4afb5ceSopenharmony_ci /* name */ "glib", 480d4afb5ceSopenharmony_ci /* init_context */ elops_init_context_glib, 481d4afb5ceSopenharmony_ci /* destroy_context1 */ NULL, 482d4afb5ceSopenharmony_ci /* destroy_context2 */ elops_destroy_context2_glib, 483d4afb5ceSopenharmony_ci /* init_vhost_listen_wsi */ elops_accept_glib, 484d4afb5ceSopenharmony_ci /* init_pt */ elops_init_pt_glib, 485d4afb5ceSopenharmony_ci /* wsi_logical_close */ elops_wsi_logical_close_glib, 486d4afb5ceSopenharmony_ci /* check_client_connect_ok */ NULL, 487d4afb5ceSopenharmony_ci /* close_handle_manually */ NULL, 488d4afb5ceSopenharmony_ci /* accept */ elops_accept_glib, 489d4afb5ceSopenharmony_ci /* io */ elops_io_glib, 490d4afb5ceSopenharmony_ci /* run_pt */ elops_run_pt_glib, 491d4afb5ceSopenharmony_ci /* destroy_pt */ elops_destroy_pt_glib, 492d4afb5ceSopenharmony_ci /* destroy wsi */ elops_destroy_wsi_glib, 493d4afb5ceSopenharmony_ci /* foreign_thread */ NULL, 494d4afb5ceSopenharmony_ci 495d4afb5ceSopenharmony_ci /* flags */ LELOF_DESTROY_FINAL, 496d4afb5ceSopenharmony_ci 497d4afb5ceSopenharmony_ci /* evlib_size_ctx */ 0, 498d4afb5ceSopenharmony_ci /* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_glib), 499d4afb5ceSopenharmony_ci /* evlib_size_vh */ 0, 500d4afb5ceSopenharmony_ci /* evlib_size_wsi */ sizeof(struct lws_io_watcher_glib), 501d4afb5ceSopenharmony_ci}; 502d4afb5ceSopenharmony_ci 503d4afb5ceSopenharmony_ci#if defined(LWS_WITH_EVLIB_PLUGINS) 504d4afb5ceSopenharmony_ciLWS_VISIBLE 505d4afb5ceSopenharmony_ci#endif 506d4afb5ceSopenharmony_ciconst lws_plugin_evlib_t evlib_glib = { 507d4afb5ceSopenharmony_ci .hdr = { 508d4afb5ceSopenharmony_ci "glib event loop", 509d4afb5ceSopenharmony_ci "lws_evlib_plugin", 510d4afb5ceSopenharmony_ci LWS_BUILD_HASH, 511d4afb5ceSopenharmony_ci LWS_PLUGIN_API_MAGIC 512d4afb5ceSopenharmony_ci }, 513d4afb5ceSopenharmony_ci 514d4afb5ceSopenharmony_ci .ops = &event_loop_ops_glib 515d4afb5ceSopenharmony_ci}; 516