xref: /aosp_15_r20/external/libwebsockets/lib/event-libs/sdevent/sdevent.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker #include <systemd/sd-event.h>
2*1c60b9acSAndroid Build Coastguard Worker 
3*1c60b9acSAndroid Build Coastguard Worker #include <private-lib-core.h>
4*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-event-libs-sdevent.h"
5*1c60b9acSAndroid Build Coastguard Worker 
6*1c60b9acSAndroid Build Coastguard Worker #define pt_to_priv_sd(_pt) ((struct lws_pt_eventlibs_sdevent *)(_pt)->evlib_pt)
7*1c60b9acSAndroid Build Coastguard Worker #define wsi_to_priv_sd(_w) ((struct lws_wsi_watcher_sdevent *)(_w)->evlib_wsi)
8*1c60b9acSAndroid Build Coastguard Worker 
9*1c60b9acSAndroid Build Coastguard Worker struct lws_pt_eventlibs_sdevent {
10*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt;
11*1c60b9acSAndroid Build Coastguard Worker 	struct sd_event *io_loop;
12*1c60b9acSAndroid Build Coastguard Worker 	struct sd_event_source *sultimer;
13*1c60b9acSAndroid Build Coastguard Worker 	struct sd_event_source *idletimer;
14*1c60b9acSAndroid Build Coastguard Worker };
15*1c60b9acSAndroid Build Coastguard Worker 
16*1c60b9acSAndroid Build Coastguard Worker struct lws_wsi_watcher_sdevent {
17*1c60b9acSAndroid Build Coastguard Worker 	struct sd_event_source *source;
18*1c60b9acSAndroid Build Coastguard Worker 	uint32_t events;
19*1c60b9acSAndroid Build Coastguard Worker };
20*1c60b9acSAndroid Build Coastguard Worker 
21*1c60b9acSAndroid Build Coastguard Worker static int
sultimer_handler(sd_event_source * s,uint64_t usec,void * userdata)22*1c60b9acSAndroid Build Coastguard Worker sultimer_handler(sd_event_source *s, uint64_t usec, void *userdata)
23*1c60b9acSAndroid Build Coastguard Worker {
24*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = (struct lws_context_per_thread *)userdata;
25*1c60b9acSAndroid Build Coastguard Worker 
26*1c60b9acSAndroid Build Coastguard Worker 	lws_usec_t us;
27*1c60b9acSAndroid Build Coastguard Worker 
28*1c60b9acSAndroid Build Coastguard Worker 	lws_context_lock(pt->context, __func__);
29*1c60b9acSAndroid Build Coastguard Worker 	lws_pt_lock(pt, __func__);
30*1c60b9acSAndroid Build Coastguard Worker 
31*1c60b9acSAndroid Build Coastguard Worker 	us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
32*1c60b9acSAndroid Build Coastguard Worker 				    lws_now_usecs());
33*1c60b9acSAndroid Build Coastguard Worker 	if (us) {
34*1c60b9acSAndroid Build Coastguard Worker 		uint64_t at;
35*1c60b9acSAndroid Build Coastguard Worker 
36*1c60b9acSAndroid Build Coastguard Worker 		sd_event_now(sd_event_source_get_event(s), CLOCK_MONOTONIC, &at);
37*1c60b9acSAndroid Build Coastguard Worker 		at += (uint64_t)us;
38*1c60b9acSAndroid Build Coastguard Worker 		sd_event_source_set_time(pt_to_priv_sd(pt)->sultimer, at);
39*1c60b9acSAndroid Build Coastguard Worker 		sd_event_source_set_enabled(pt_to_priv_sd(pt)->sultimer,
40*1c60b9acSAndroid Build Coastguard Worker 					    SD_EVENT_ONESHOT);
41*1c60b9acSAndroid Build Coastguard Worker 	}
42*1c60b9acSAndroid Build Coastguard Worker 
43*1c60b9acSAndroid Build Coastguard Worker 	lws_pt_unlock(pt);
44*1c60b9acSAndroid Build Coastguard Worker 	lws_context_unlock(pt->context);
45*1c60b9acSAndroid Build Coastguard Worker 
46*1c60b9acSAndroid Build Coastguard Worker 	return 0;
47*1c60b9acSAndroid Build Coastguard Worker }
48*1c60b9acSAndroid Build Coastguard Worker 
49*1c60b9acSAndroid Build Coastguard Worker static int
idle_handler(sd_event_source * s,uint64_t usec,void * userdata)50*1c60b9acSAndroid Build Coastguard Worker idle_handler(sd_event_source *s, uint64_t usec, void *userdata)
51*1c60b9acSAndroid Build Coastguard Worker {
52*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = (struct lws_context_per_thread *)userdata;
53*1c60b9acSAndroid Build Coastguard Worker 
54*1c60b9acSAndroid Build Coastguard Worker 	lws_usec_t us;
55*1c60b9acSAndroid Build Coastguard Worker 
56*1c60b9acSAndroid Build Coastguard Worker 	lws_service_do_ripe_rxflow(pt);
57*1c60b9acSAndroid Build Coastguard Worker 
58*1c60b9acSAndroid Build Coastguard Worker 	lws_context_lock(pt->context, __func__);
59*1c60b9acSAndroid Build Coastguard Worker 	lws_pt_lock(pt, __func__);
60*1c60b9acSAndroid Build Coastguard Worker 
61*1c60b9acSAndroid Build Coastguard Worker 	/*
62*1c60b9acSAndroid Build Coastguard Worker 	 * is there anybody with pending stuff that needs service forcing?
63*1c60b9acSAndroid Build Coastguard Worker 	 */
64*1c60b9acSAndroid Build Coastguard Worker 	 if (!lws_service_adjust_timeout(pt->context, 1, pt->tid))
65*1c60b9acSAndroid Build Coastguard Worker 		 /* -1 timeout means just do forced service */
66*1c60b9acSAndroid Build Coastguard Worker 		 _lws_plat_service_forced_tsi(pt->context, pt->tid);
67*1c60b9acSAndroid Build Coastguard Worker 
68*1c60b9acSAndroid Build Coastguard Worker 	 /* account for sultimer */
69*1c60b9acSAndroid Build Coastguard Worker 
70*1c60b9acSAndroid Build Coastguard Worker 	 us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
71*1c60b9acSAndroid Build Coastguard Worker 				     lws_now_usecs());
72*1c60b9acSAndroid Build Coastguard Worker 
73*1c60b9acSAndroid Build Coastguard Worker 	 if (us) {
74*1c60b9acSAndroid Build Coastguard Worker 		 uint64_t at;
75*1c60b9acSAndroid Build Coastguard Worker 
76*1c60b9acSAndroid Build Coastguard Worker 		 sd_event_now(sd_event_source_get_event(s), CLOCK_MONOTONIC, &at);
77*1c60b9acSAndroid Build Coastguard Worker 		 at += (uint64_t)us;
78*1c60b9acSAndroid Build Coastguard Worker 		 sd_event_source_set_time(pt_to_priv_sd(pt)->sultimer, at);
79*1c60b9acSAndroid Build Coastguard Worker 		 sd_event_source_set_enabled(pt_to_priv_sd(pt)->sultimer,
80*1c60b9acSAndroid Build Coastguard Worker 					     SD_EVENT_ONESHOT);
81*1c60b9acSAndroid Build Coastguard Worker 	 }
82*1c60b9acSAndroid Build Coastguard Worker 
83*1c60b9acSAndroid Build Coastguard Worker 	 sd_event_source_set_enabled(pt_to_priv_sd(pt)->idletimer, SD_EVENT_OFF);
84*1c60b9acSAndroid Build Coastguard Worker 
85*1c60b9acSAndroid Build Coastguard Worker 	 lws_pt_unlock(pt);
86*1c60b9acSAndroid Build Coastguard Worker 	 lws_context_unlock(pt->context);
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
sock_accept_handler(sd_event_source * s,int fd,uint32_t revents,void * userdata)92*1c60b9acSAndroid Build Coastguard Worker sock_accept_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata)
93*1c60b9acSAndroid Build Coastguard Worker {
94*1c60b9acSAndroid Build Coastguard Worker 	struct lws *wsi = (struct lws *)userdata;
95*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *context = wsi->a.context;
96*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
97*1c60b9acSAndroid Build Coastguard Worker 	struct sd_event_source *idletimer, *watcher;
98*1c60b9acSAndroid Build Coastguard Worker 	struct lws_pollfd eventfd;
99*1c60b9acSAndroid Build Coastguard Worker 
100*1c60b9acSAndroid Build Coastguard Worker 	lws_context_lock(pt->context, __func__);
101*1c60b9acSAndroid Build Coastguard Worker 	lws_pt_lock(pt, __func__);
102*1c60b9acSAndroid Build Coastguard Worker 
103*1c60b9acSAndroid Build Coastguard Worker 	if (pt->is_destroyed)
104*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
105*1c60b9acSAndroid Build Coastguard Worker 
106*1c60b9acSAndroid Build Coastguard Worker 	eventfd.fd = fd;
107*1c60b9acSAndroid Build Coastguard Worker 	eventfd.events = 0;
108*1c60b9acSAndroid Build Coastguard Worker 	eventfd.revents = 0;
109*1c60b9acSAndroid Build Coastguard Worker 
110*1c60b9acSAndroid Build Coastguard Worker 	if (revents & EPOLLIN) {
111*1c60b9acSAndroid Build Coastguard Worker 		eventfd.events |= LWS_POLLIN;
112*1c60b9acSAndroid Build Coastguard Worker 		eventfd.revents |= LWS_POLLIN;
113*1c60b9acSAndroid Build Coastguard Worker 	}
114*1c60b9acSAndroid Build Coastguard Worker 
115*1c60b9acSAndroid Build Coastguard Worker 	if (revents & EPOLLOUT) {
116*1c60b9acSAndroid Build Coastguard Worker 		eventfd.events |= LWS_POLLOUT;
117*1c60b9acSAndroid Build Coastguard Worker 		eventfd.revents |= LWS_POLLOUT;
118*1c60b9acSAndroid Build Coastguard Worker 	}
119*1c60b9acSAndroid Build Coastguard Worker 
120*1c60b9acSAndroid Build Coastguard Worker 	lws_pt_unlock(pt);
121*1c60b9acSAndroid Build Coastguard Worker 	lws_context_unlock(pt->context);
122*1c60b9acSAndroid Build Coastguard Worker 
123*1c60b9acSAndroid Build Coastguard Worker 	lws_service_fd_tsi(context, &eventfd, wsi->tsi);
124*1c60b9acSAndroid Build Coastguard Worker 
125*1c60b9acSAndroid Build Coastguard Worker 	if (pt->destroy_self) {
126*1c60b9acSAndroid Build Coastguard Worker 		lws_context_destroy(pt->context);
127*1c60b9acSAndroid Build Coastguard Worker 		return -1;
128*1c60b9acSAndroid Build Coastguard Worker 	}
129*1c60b9acSAndroid Build Coastguard Worker 
130*1c60b9acSAndroid Build Coastguard Worker 	/* fire idle handler */
131*1c60b9acSAndroid Build Coastguard Worker 	idletimer = pt_to_priv_sd(pt)->idletimer;
132*1c60b9acSAndroid Build Coastguard Worker 	if (idletimer) {
133*1c60b9acSAndroid Build Coastguard Worker 		sd_event_source_set_time(idletimer, (uint64_t) 0);
134*1c60b9acSAndroid Build Coastguard Worker 		sd_event_source_set_enabled(idletimer, SD_EVENT_ON);
135*1c60b9acSAndroid Build Coastguard Worker 	}
136*1c60b9acSAndroid Build Coastguard Worker 
137*1c60b9acSAndroid Build Coastguard Worker 	/*
138*1c60b9acSAndroid Build Coastguard Worker 	 * allow further events
139*1c60b9acSAndroid Build Coastguard Worker 	 *
140*1c60b9acSAndroid Build Coastguard Worker 	 * Note:
141*1c60b9acSAndroid Build Coastguard Worker 	 * do not move the assignment up, lws_service_fd_tsi may invalidate it!
142*1c60b9acSAndroid Build Coastguard Worker 	 */
143*1c60b9acSAndroid Build Coastguard Worker 	watcher = wsi_to_priv_sd(wsi)->source;
144*1c60b9acSAndroid Build Coastguard Worker 	if (watcher)
145*1c60b9acSAndroid Build Coastguard Worker 		sd_event_source_set_enabled(watcher, SD_EVENT_ONESHOT);
146*1c60b9acSAndroid Build Coastguard Worker 
147*1c60b9acSAndroid Build Coastguard Worker 	return 0;
148*1c60b9acSAndroid Build Coastguard Worker 
149*1c60b9acSAndroid Build Coastguard Worker bail:
150*1c60b9acSAndroid Build Coastguard Worker 	lws_pt_unlock(pt);
151*1c60b9acSAndroid Build Coastguard Worker 	lws_context_unlock(pt->context);
152*1c60b9acSAndroid Build Coastguard Worker 
153*1c60b9acSAndroid Build Coastguard Worker 	return -1;
154*1c60b9acSAndroid Build Coastguard Worker }
155*1c60b9acSAndroid Build Coastguard Worker 
156*1c60b9acSAndroid Build Coastguard Worker static void
io_sd(struct lws * wsi,unsigned int flags)157*1c60b9acSAndroid Build Coastguard Worker io_sd(struct lws *wsi, unsigned int flags)
158*1c60b9acSAndroid Build Coastguard Worker {
159*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
160*1c60b9acSAndroid Build Coastguard Worker 
161*1c60b9acSAndroid Build Coastguard Worker 	/*
162*1c60b9acSAndroid Build Coastguard Worker 	 * Only manipulate if there is an event source, and if
163*1c60b9acSAndroid Build Coastguard Worker 	 * the pt is still alive
164*1c60b9acSAndroid Build Coastguard Worker 	 */
165*1c60b9acSAndroid Build Coastguard Worker 	if (!pt_to_priv_sd(pt)->io_loop ||
166*1c60b9acSAndroid Build Coastguard Worker 	    !wsi_to_priv_sd(wsi)->source ||
167*1c60b9acSAndroid Build Coastguard Worker 	    pt->is_destroyed)
168*1c60b9acSAndroid Build Coastguard Worker 		return;
169*1c60b9acSAndroid Build Coastguard Worker 
170*1c60b9acSAndroid Build Coastguard Worker 	// assert that the requested flags do not contain anything unexpected
171*1c60b9acSAndroid Build Coastguard Worker 	if (!((flags & (LWS_EV_START | LWS_EV_STOP)) &&
172*1c60b9acSAndroid Build Coastguard Worker 	    (flags & (LWS_EV_READ | LWS_EV_WRITE)))) {
173*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_err(wsi, "assert: flags %d", flags);
174*1c60b9acSAndroid Build Coastguard Worker 		assert(0);
175*1c60b9acSAndroid Build Coastguard Worker 	}
176*1c60b9acSAndroid Build Coastguard Worker 
177*1c60b9acSAndroid Build Coastguard Worker 	// we are overdoing a bit here, so it resembles the structure in libuv.c
178*1c60b9acSAndroid Build Coastguard Worker 	if (flags & LWS_EV_START) {
179*1c60b9acSAndroid Build Coastguard Worker 		if (flags & LWS_EV_WRITE)
180*1c60b9acSAndroid Build Coastguard Worker 			wsi_to_priv_sd(wsi)->events |= EPOLLOUT;
181*1c60b9acSAndroid Build Coastguard Worker 
182*1c60b9acSAndroid Build Coastguard Worker 		if (flags & LWS_EV_READ)
183*1c60b9acSAndroid Build Coastguard Worker 			wsi_to_priv_sd(wsi)->events |= EPOLLIN;
184*1c60b9acSAndroid Build Coastguard Worker 
185*1c60b9acSAndroid Build Coastguard Worker 		sd_event_source_set_io_events(wsi_to_priv_sd(wsi)->source,
186*1c60b9acSAndroid Build Coastguard Worker 					      wsi_to_priv_sd(wsi)->events);
187*1c60b9acSAndroid Build Coastguard Worker 		sd_event_source_set_enabled(wsi_to_priv_sd(wsi)->source,
188*1c60b9acSAndroid Build Coastguard Worker 					    SD_EVENT_ONESHOT);
189*1c60b9acSAndroid Build Coastguard Worker 	} else {
190*1c60b9acSAndroid Build Coastguard Worker 		if (flags & LWS_EV_WRITE)
191*1c60b9acSAndroid Build Coastguard Worker 			wsi_to_priv_sd(wsi)->events =
192*1c60b9acSAndroid Build Coastguard Worker 				wsi_to_priv_sd(wsi)->events &
193*1c60b9acSAndroid Build Coastguard Worker 					(uint32_t)(~EPOLLOUT);
194*1c60b9acSAndroid Build Coastguard Worker 
195*1c60b9acSAndroid Build Coastguard Worker 		if (flags & LWS_EV_READ)
196*1c60b9acSAndroid Build Coastguard Worker 			wsi_to_priv_sd(wsi)->events =
197*1c60b9acSAndroid Build Coastguard Worker 				wsi_to_priv_sd(wsi)->events &
198*1c60b9acSAndroid Build Coastguard Worker 					(uint32_t)(~EPOLLIN);
199*1c60b9acSAndroid Build Coastguard Worker 
200*1c60b9acSAndroid Build Coastguard Worker 		sd_event_source_set_io_events(wsi_to_priv_sd(wsi)->source,
201*1c60b9acSAndroid Build Coastguard Worker 					      wsi_to_priv_sd(wsi)->events);
202*1c60b9acSAndroid Build Coastguard Worker 
203*1c60b9acSAndroid Build Coastguard Worker 		if (!(wsi_to_priv_sd(wsi)->events & (EPOLLIN | EPOLLOUT)))
204*1c60b9acSAndroid Build Coastguard Worker 			sd_event_source_set_enabled(wsi_to_priv_sd(wsi)->source,
205*1c60b9acSAndroid Build Coastguard Worker 						    SD_EVENT_ONESHOT);
206*1c60b9acSAndroid Build Coastguard Worker 		else
207*1c60b9acSAndroid Build Coastguard Worker 			sd_event_source_set_enabled(wsi_to_priv_sd(wsi)->source,
208*1c60b9acSAndroid Build Coastguard Worker 						    SD_EVENT_OFF);
209*1c60b9acSAndroid Build Coastguard Worker 	}
210*1c60b9acSAndroid Build Coastguard Worker }
211*1c60b9acSAndroid Build Coastguard Worker 
212*1c60b9acSAndroid Build Coastguard Worker static int
init_vhost_listen_wsi_sd(struct lws * wsi)213*1c60b9acSAndroid Build Coastguard Worker init_vhost_listen_wsi_sd(struct lws *wsi)
214*1c60b9acSAndroid Build Coastguard Worker {
215*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt;
216*1c60b9acSAndroid Build Coastguard Worker 
217*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi)
218*1c60b9acSAndroid Build Coastguard Worker 		return 0;
219*1c60b9acSAndroid Build Coastguard Worker 
220*1c60b9acSAndroid Build Coastguard Worker 	pt = &wsi->a.context->pt[(int)wsi->tsi];
221*1c60b9acSAndroid Build Coastguard Worker 
222*1c60b9acSAndroid Build Coastguard Worker 	sd_event_add_io(pt_to_priv_sd(pt)->io_loop,
223*1c60b9acSAndroid Build Coastguard Worker 			&wsi_to_priv_sd(wsi)->source,
224*1c60b9acSAndroid Build Coastguard Worker 			wsi->desc.sockfd,
225*1c60b9acSAndroid Build Coastguard Worker 			wsi_to_priv_sd(wsi)->events,
226*1c60b9acSAndroid Build Coastguard Worker 			sock_accept_handler,
227*1c60b9acSAndroid Build Coastguard Worker 			wsi);
228*1c60b9acSAndroid Build Coastguard Worker 
229*1c60b9acSAndroid Build Coastguard Worker 	io_sd(wsi, LWS_EV_START | LWS_EV_READ);
230*1c60b9acSAndroid Build Coastguard Worker 
231*1c60b9acSAndroid Build Coastguard Worker 	return 0;
232*1c60b9acSAndroid Build Coastguard Worker }
233*1c60b9acSAndroid Build Coastguard Worker 
234*1c60b9acSAndroid Build Coastguard Worker static int
elops_listen_init_sdevent(struct lws_dll2 * d,void * user)235*1c60b9acSAndroid Build Coastguard Worker elops_listen_init_sdevent(struct lws_dll2 *d, void *user)
236*1c60b9acSAndroid Build Coastguard Worker {
237*1c60b9acSAndroid Build Coastguard Worker 	struct lws *wsi = lws_container_of(d, struct lws, listen_list);
238*1c60b9acSAndroid Build Coastguard Worker 
239*1c60b9acSAndroid Build Coastguard Worker 	if (init_vhost_listen_wsi_sd(wsi) == -1)
240*1c60b9acSAndroid Build Coastguard Worker 		return -1;
241*1c60b9acSAndroid Build Coastguard Worker 
242*1c60b9acSAndroid Build Coastguard Worker 	return 0;
243*1c60b9acSAndroid Build Coastguard Worker }
244*1c60b9acSAndroid Build Coastguard Worker 
245*1c60b9acSAndroid Build Coastguard Worker static int
init_pt_sd(struct lws_context * context,void * _loop,int tsi)246*1c60b9acSAndroid Build Coastguard Worker init_pt_sd(struct lws_context *context, void *_loop, int tsi)
247*1c60b9acSAndroid Build Coastguard Worker {
248*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &context->pt[tsi];
249*1c60b9acSAndroid Build Coastguard Worker 	struct lws_pt_eventlibs_sdevent *ptpriv = pt_to_priv_sd(pt);
250*1c60b9acSAndroid Build Coastguard Worker 	struct sd_event *loop = (struct sd_event *)_loop;
251*1c60b9acSAndroid Build Coastguard Worker 	int first = 1;  /* first to create and initialize the loop */
252*1c60b9acSAndroid Build Coastguard Worker 
253*1c60b9acSAndroid Build Coastguard Worker 	ptpriv->pt = pt;
254*1c60b9acSAndroid Build Coastguard Worker 
255*1c60b9acSAndroid Build Coastguard Worker 	/* make sure we have an event loop */
256*1c60b9acSAndroid Build Coastguard Worker 	if (!ptpriv->io_loop) {
257*1c60b9acSAndroid Build Coastguard Worker 		if (!loop) {
258*1c60b9acSAndroid Build Coastguard Worker 			if (sd_event_default(&loop) < 0) {
259*1c60b9acSAndroid Build Coastguard Worker 				lwsl_cx_err(context, "sd_event_default failed");
260*1c60b9acSAndroid Build Coastguard Worker 
261*1c60b9acSAndroid Build Coastguard Worker 				return -1;
262*1c60b9acSAndroid Build Coastguard Worker 			}
263*1c60b9acSAndroid Build Coastguard Worker 			pt->event_loop_foreign = 0;
264*1c60b9acSAndroid Build Coastguard Worker 		} else {
265*1c60b9acSAndroid Build Coastguard Worker 			sd_event_ref(loop);
266*1c60b9acSAndroid Build Coastguard Worker 			pt->event_loop_foreign = 1;
267*1c60b9acSAndroid Build Coastguard Worker 		}
268*1c60b9acSAndroid Build Coastguard Worker 
269*1c60b9acSAndroid Build Coastguard Worker 		ptpriv->io_loop = loop;
270*1c60b9acSAndroid Build Coastguard Worker 	} else
271*1c60b9acSAndroid Build Coastguard Worker 		 /*
272*1c60b9acSAndroid Build Coastguard Worker 		  * If the loop was initialized before, we do not need to
273*1c60b9acSAndroid Build Coastguard Worker 		  * do full initialization
274*1c60b9acSAndroid Build Coastguard Worker 		  */
275*1c60b9acSAndroid Build Coastguard Worker 		first = 0;
276*1c60b9acSAndroid Build Coastguard Worker 
277*1c60b9acSAndroid Build Coastguard Worker 	lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_init_sdevent);
278*1c60b9acSAndroid Build Coastguard Worker 
279*1c60b9acSAndroid Build Coastguard Worker 	if (first) {
280*1c60b9acSAndroid Build Coastguard Worker 
281*1c60b9acSAndroid Build Coastguard Worker 		if (0 > sd_event_add_time(loop,
282*1c60b9acSAndroid Build Coastguard Worker 				&ptpriv->sultimer,
283*1c60b9acSAndroid Build Coastguard Worker 				CLOCK_MONOTONIC,
284*1c60b9acSAndroid Build Coastguard Worker 				UINT64_MAX,
285*1c60b9acSAndroid Build Coastguard Worker 				0,
286*1c60b9acSAndroid Build Coastguard Worker 				sultimer_handler,
287*1c60b9acSAndroid Build Coastguard Worker 				(void*) pt
288*1c60b9acSAndroid Build Coastguard Worker 		))
289*1c60b9acSAndroid Build Coastguard Worker 			return -1;
290*1c60b9acSAndroid Build Coastguard Worker 
291*1c60b9acSAndroid Build Coastguard Worker 		if (0 > sd_event_add_time(loop,
292*1c60b9acSAndroid Build Coastguard Worker 				&ptpriv->idletimer,
293*1c60b9acSAndroid Build Coastguard Worker 				CLOCK_MONOTONIC,
294*1c60b9acSAndroid Build Coastguard Worker 				0,
295*1c60b9acSAndroid Build Coastguard Worker 				0,
296*1c60b9acSAndroid Build Coastguard Worker 				idle_handler,
297*1c60b9acSAndroid Build Coastguard Worker 				(void *)pt))
298*1c60b9acSAndroid Build Coastguard Worker 			return -1;
299*1c60b9acSAndroid Build Coastguard Worker 
300*1c60b9acSAndroid Build Coastguard Worker 		sd_event_source_set_enabled(ptpriv->idletimer, SD_EVENT_ON);
301*1c60b9acSAndroid Build Coastguard Worker 
302*1c60b9acSAndroid Build Coastguard Worker 		if (0 > sd_event_source_set_priority(ptpriv->idletimer,
303*1c60b9acSAndroid Build Coastguard Worker 						     SD_EVENT_PRIORITY_IDLE))
304*1c60b9acSAndroid Build Coastguard Worker 			return -1;
305*1c60b9acSAndroid Build Coastguard Worker 
306*1c60b9acSAndroid Build Coastguard Worker 	}
307*1c60b9acSAndroid Build Coastguard Worker 
308*1c60b9acSAndroid Build Coastguard Worker 	return 0;
309*1c60b9acSAndroid Build Coastguard Worker }
310*1c60b9acSAndroid Build Coastguard Worker 
311*1c60b9acSAndroid Build Coastguard Worker static void
wsi_destroy_sd(struct lws * wsi)312*1c60b9acSAndroid Build Coastguard Worker wsi_destroy_sd(struct lws *wsi)
313*1c60b9acSAndroid Build Coastguard Worker {
314*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi)
315*1c60b9acSAndroid Build Coastguard Worker 		return;
316*1c60b9acSAndroid Build Coastguard Worker 
317*1c60b9acSAndroid Build Coastguard Worker 	io_sd(wsi, LWS_EV_STOP | (LWS_EV_READ | LWS_EV_WRITE));
318*1c60b9acSAndroid Build Coastguard Worker 
319*1c60b9acSAndroid Build Coastguard Worker 	if (wsi_to_priv_sd(wsi)->source) {
320*1c60b9acSAndroid Build Coastguard Worker 		sd_event_source_set_enabled(wsi_to_priv_sd(wsi)->source,
321*1c60b9acSAndroid Build Coastguard Worker 					    SD_EVENT_OFF);
322*1c60b9acSAndroid Build Coastguard Worker 		sd_event_source_unref(wsi_to_priv_sd(wsi)->source);
323*1c60b9acSAndroid Build Coastguard Worker 		wsi_to_priv_sd(wsi)->source = NULL;
324*1c60b9acSAndroid Build Coastguard Worker 	}
325*1c60b9acSAndroid Build Coastguard Worker }
326*1c60b9acSAndroid Build Coastguard Worker 
327*1c60b9acSAndroid Build Coastguard Worker static int
wsi_logical_close_sd(struct lws * wsi)328*1c60b9acSAndroid Build Coastguard Worker wsi_logical_close_sd(struct lws *wsi)
329*1c60b9acSAndroid Build Coastguard Worker {
330*1c60b9acSAndroid Build Coastguard Worker 	wsi_destroy_sd(wsi);
331*1c60b9acSAndroid Build Coastguard Worker 
332*1c60b9acSAndroid Build Coastguard Worker 	return 0;
333*1c60b9acSAndroid Build Coastguard Worker }
334*1c60b9acSAndroid Build Coastguard Worker 
335*1c60b9acSAndroid Build Coastguard Worker static int
sock_accept_sd(struct lws * wsi)336*1c60b9acSAndroid Build Coastguard Worker sock_accept_sd(struct lws *wsi)
337*1c60b9acSAndroid Build Coastguard Worker {
338*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
339*1c60b9acSAndroid Build Coastguard Worker 
340*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->role_ops->file_handle)
341*1c60b9acSAndroid Build Coastguard Worker 		sd_event_add_io(pt_to_priv_sd(pt)->io_loop,
342*1c60b9acSAndroid Build Coastguard Worker 				&wsi_to_priv_sd(wsi)->source,
343*1c60b9acSAndroid Build Coastguard Worker 				wsi->desc.filefd,
344*1c60b9acSAndroid Build Coastguard Worker 				wsi_to_priv_sd(wsi)->events,
345*1c60b9acSAndroid Build Coastguard Worker 				sock_accept_handler,
346*1c60b9acSAndroid Build Coastguard Worker 				wsi);
347*1c60b9acSAndroid Build Coastguard Worker 	else
348*1c60b9acSAndroid Build Coastguard Worker 		sd_event_add_io(pt_to_priv_sd(pt)->io_loop,
349*1c60b9acSAndroid Build Coastguard Worker 				&wsi_to_priv_sd(wsi)->source,
350*1c60b9acSAndroid Build Coastguard Worker 				wsi->desc.sockfd,
351*1c60b9acSAndroid Build Coastguard Worker 				wsi_to_priv_sd(wsi)->events,
352*1c60b9acSAndroid Build Coastguard Worker 				sock_accept_handler,
353*1c60b9acSAndroid Build Coastguard Worker 				wsi);
354*1c60b9acSAndroid Build Coastguard Worker 
355*1c60b9acSAndroid Build Coastguard Worker 	return 0;
356*1c60b9acSAndroid Build Coastguard Worker }
357*1c60b9acSAndroid Build Coastguard Worker 
358*1c60b9acSAndroid Build Coastguard Worker static void
run_pt_sd(struct lws_context * context,int tsi)359*1c60b9acSAndroid Build Coastguard Worker run_pt_sd(struct lws_context *context, int tsi)
360*1c60b9acSAndroid Build Coastguard Worker {
361*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &context->pt[tsi];
362*1c60b9acSAndroid Build Coastguard Worker 	struct lws_pt_eventlibs_sdevent *ptpriv = pt_to_priv_sd(pt);
363*1c60b9acSAndroid Build Coastguard Worker 
364*1c60b9acSAndroid Build Coastguard Worker 	if (ptpriv->io_loop)
365*1c60b9acSAndroid Build Coastguard Worker 		sd_event_run(ptpriv->io_loop, (uint64_t) -1);
366*1c60b9acSAndroid Build Coastguard Worker }
367*1c60b9acSAndroid Build Coastguard Worker 
368*1c60b9acSAndroid Build Coastguard Worker static int
elops_listen_destroy_sdevent(struct lws_dll2 * d,void * user)369*1c60b9acSAndroid Build Coastguard Worker elops_listen_destroy_sdevent(struct lws_dll2 *d, void *user)
370*1c60b9acSAndroid Build Coastguard Worker {
371*1c60b9acSAndroid Build Coastguard Worker 	struct lws *wsi = lws_container_of(d, struct lws, listen_list);
372*1c60b9acSAndroid Build Coastguard Worker 
373*1c60b9acSAndroid Build Coastguard Worker 	wsi_logical_close_sd(wsi);
374*1c60b9acSAndroid Build Coastguard Worker 
375*1c60b9acSAndroid Build Coastguard Worker 	return 0;
376*1c60b9acSAndroid Build Coastguard Worker }
377*1c60b9acSAndroid Build Coastguard Worker 
378*1c60b9acSAndroid Build Coastguard Worker static void
destroy_pt_sd(struct lws_context * context,int tsi)379*1c60b9acSAndroid Build Coastguard Worker destroy_pt_sd(struct lws_context *context, int tsi)
380*1c60b9acSAndroid Build Coastguard Worker {
381*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &context->pt[tsi];
382*1c60b9acSAndroid Build Coastguard Worker 	struct lws_pt_eventlibs_sdevent *ptpriv = pt_to_priv_sd(pt);
383*1c60b9acSAndroid Build Coastguard Worker 
384*1c60b9acSAndroid Build Coastguard Worker 	lws_vhost_foreach_listen_wsi(context, NULL, elops_listen_destroy_sdevent);
385*1c60b9acSAndroid Build Coastguard Worker 
386*1c60b9acSAndroid Build Coastguard Worker 	if (ptpriv->sultimer) {
387*1c60b9acSAndroid Build Coastguard Worker 		sd_event_source_set_enabled(ptpriv->sultimer,
388*1c60b9acSAndroid Build Coastguard Worker 					    SD_EVENT_OFF);
389*1c60b9acSAndroid Build Coastguard Worker 		sd_event_source_unref(ptpriv->sultimer);
390*1c60b9acSAndroid Build Coastguard Worker 		ptpriv->sultimer = NULL;
391*1c60b9acSAndroid Build Coastguard Worker 	}
392*1c60b9acSAndroid Build Coastguard Worker 
393*1c60b9acSAndroid Build Coastguard Worker 	if (ptpriv->idletimer) {
394*1c60b9acSAndroid Build Coastguard Worker 		sd_event_source_set_enabled(ptpriv->idletimer,
395*1c60b9acSAndroid Build Coastguard Worker 					    SD_EVENT_OFF);
396*1c60b9acSAndroid Build Coastguard Worker 		sd_event_source_unref(ptpriv->idletimer);
397*1c60b9acSAndroid Build Coastguard Worker 		ptpriv->idletimer = NULL;
398*1c60b9acSAndroid Build Coastguard Worker 	}
399*1c60b9acSAndroid Build Coastguard Worker 
400*1c60b9acSAndroid Build Coastguard Worker 	if (ptpriv->io_loop) {
401*1c60b9acSAndroid Build Coastguard Worker 		sd_event_unref(ptpriv->io_loop);
402*1c60b9acSAndroid Build Coastguard Worker 		ptpriv->io_loop = NULL;
403*1c60b9acSAndroid Build Coastguard Worker 	}
404*1c60b9acSAndroid Build Coastguard Worker }
405*1c60b9acSAndroid Build Coastguard Worker 
406*1c60b9acSAndroid Build Coastguard Worker const struct lws_event_loop_ops event_loop_ops_sdevent = {
407*1c60b9acSAndroid Build Coastguard Worker 		.name				= "sdevent",
408*1c60b9acSAndroid Build Coastguard Worker 		.init_context			= NULL,
409*1c60b9acSAndroid Build Coastguard Worker 		.destroy_context1		= NULL,
410*1c60b9acSAndroid Build Coastguard Worker 		.destroy_context2		= NULL,
411*1c60b9acSAndroid Build Coastguard Worker 		.init_vhost_listen_wsi		= init_vhost_listen_wsi_sd,
412*1c60b9acSAndroid Build Coastguard Worker 		.init_pt			= init_pt_sd,
413*1c60b9acSAndroid Build Coastguard Worker 		.wsi_logical_close		= wsi_logical_close_sd,
414*1c60b9acSAndroid Build Coastguard Worker 		.check_client_connect_ok	= NULL,
415*1c60b9acSAndroid Build Coastguard Worker 		.close_handle_manually		= NULL,
416*1c60b9acSAndroid Build Coastguard Worker 		.sock_accept			= sock_accept_sd,
417*1c60b9acSAndroid Build Coastguard Worker 		.io				= io_sd,
418*1c60b9acSAndroid Build Coastguard Worker 		.run_pt				= run_pt_sd,
419*1c60b9acSAndroid Build Coastguard Worker 		.destroy_pt			= destroy_pt_sd,
420*1c60b9acSAndroid Build Coastguard Worker 		.destroy_wsi			= wsi_destroy_sd,
421*1c60b9acSAndroid Build Coastguard Worker 
422*1c60b9acSAndroid Build Coastguard Worker 		.flags				= 0,
423*1c60b9acSAndroid Build Coastguard Worker 
424*1c60b9acSAndroid Build Coastguard Worker 		.evlib_size_ctx			= 0,
425*1c60b9acSAndroid Build Coastguard Worker 		.evlib_size_pt			= sizeof(struct lws_pt_eventlibs_sdevent),
426*1c60b9acSAndroid Build Coastguard Worker 		.evlib_size_vh			= 0,
427*1c60b9acSAndroid Build Coastguard Worker 		.evlib_size_wsi			= sizeof(struct lws_wsi_watcher_sdevent),
428*1c60b9acSAndroid Build Coastguard Worker };
429*1c60b9acSAndroid Build Coastguard Worker 
430*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_EVLIB_PLUGINS)
431*1c60b9acSAndroid Build Coastguard Worker LWS_VISIBLE
432*1c60b9acSAndroid Build Coastguard Worker #endif
433*1c60b9acSAndroid Build Coastguard Worker const lws_plugin_evlib_t evlib_sd = {
434*1c60b9acSAndroid Build Coastguard Worker 		.hdr = {
435*1c60b9acSAndroid Build Coastguard Worker 				"systemd event loop",
436*1c60b9acSAndroid Build Coastguard Worker 				"lws_evlib_plugin",
437*1c60b9acSAndroid Build Coastguard Worker 				LWS_BUILD_HASH,
438*1c60b9acSAndroid Build Coastguard Worker 				LWS_PLUGIN_API_MAGIC
439*1c60b9acSAndroid Build Coastguard Worker 		},
440*1c60b9acSAndroid Build Coastguard Worker 
441*1c60b9acSAndroid Build Coastguard Worker 		.ops	= &event_loop_ops_sdevent
442*1c60b9acSAndroid Build Coastguard Worker };
443