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