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