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#include "private-lib-event-libs-libev.h"
27d4afb5ceSopenharmony_ci
28d4afb5ceSopenharmony_ci#define pt_to_priv_ev(_pt) ((struct lws_pt_eventlibs_libev *)(_pt)->evlib_pt)
29d4afb5ceSopenharmony_ci#define vh_to_priv_ev(_vh) ((struct lws_vh_eventlibs_libev *)(_vh)->evlib_vh)
30d4afb5ceSopenharmony_ci#define wsi_to_priv_ev(_w) ((struct lws_wsi_eventlibs_libev *)(_w)->evlib_wsi)
31d4afb5ceSopenharmony_ci
32d4afb5ceSopenharmony_cistatic void
33d4afb5ceSopenharmony_cilws_ev_hrtimer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)
34d4afb5ceSopenharmony_ci{
35d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libev *ptpr = lws_container_of(watcher,
36d4afb5ceSopenharmony_ci					struct lws_pt_eventlibs_libev, hrtimer);
37d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = ptpr->pt;
38d4afb5ceSopenharmony_ci	lws_usec_t us;
39d4afb5ceSopenharmony_ci
40d4afb5ceSopenharmony_ci	lws_pt_lock(pt, __func__);
41d4afb5ceSopenharmony_ci	us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
42d4afb5ceSopenharmony_ci				    lws_now_usecs());
43d4afb5ceSopenharmony_ci	if (us) {
44d4afb5ceSopenharmony_ci		ev_timer_set(&ptpr->hrtimer, ((float)us) / 1000000.0, 0);
45d4afb5ceSopenharmony_ci		ev_timer_start(ptpr->io_loop, &ptpr->hrtimer);
46d4afb5ceSopenharmony_ci	}
47d4afb5ceSopenharmony_ci	lws_pt_unlock(pt);
48d4afb5ceSopenharmony_ci}
49d4afb5ceSopenharmony_ci
50d4afb5ceSopenharmony_cistatic void
51d4afb5ceSopenharmony_cilws_ev_idle_cb(struct ev_loop *loop, struct ev_idle *handle, int revents)
52d4afb5ceSopenharmony_ci{
53d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libev *ptpr = lws_container_of(handle,
54d4afb5ceSopenharmony_ci					struct lws_pt_eventlibs_libev, idle);
55d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = ptpr->pt;
56d4afb5ceSopenharmony_ci	int reschedule = 0;
57d4afb5ceSopenharmony_ci	lws_usec_t us;
58d4afb5ceSopenharmony_ci
59d4afb5ceSopenharmony_ci	lws_service_do_ripe_rxflow(pt);
60d4afb5ceSopenharmony_ci
61d4afb5ceSopenharmony_ci	/*
62d4afb5ceSopenharmony_ci	 * is there anybody with pending stuff that needs service forcing?
63d4afb5ceSopenharmony_ci	 */
64d4afb5ceSopenharmony_ci	if (!lws_service_adjust_timeout(pt->context, 1, pt->tid))
65d4afb5ceSopenharmony_ci		/* -1 timeout means just do forced service */
66d4afb5ceSopenharmony_ci		reschedule = _lws_plat_service_forced_tsi(pt->context, pt->tid);
67d4afb5ceSopenharmony_ci
68d4afb5ceSopenharmony_ci	/* account for hrtimer */
69d4afb5ceSopenharmony_ci
70d4afb5ceSopenharmony_ci	lws_pt_lock(pt, __func__);
71d4afb5ceSopenharmony_ci	us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
72d4afb5ceSopenharmony_ci				    lws_now_usecs());
73d4afb5ceSopenharmony_ci	if (us) {
74d4afb5ceSopenharmony_ci		ev_timer_set(&ptpr->hrtimer, ((float)us) / 1000000.0, 0);
75d4afb5ceSopenharmony_ci		ev_timer_start(ptpr->io_loop, &ptpr->hrtimer);
76d4afb5ceSopenharmony_ci	}
77d4afb5ceSopenharmony_ci	lws_pt_unlock(pt);
78d4afb5ceSopenharmony_ci
79d4afb5ceSopenharmony_ci	/* there is nobody who needs service forcing, shut down idle */
80d4afb5ceSopenharmony_ci	if (!reschedule)
81d4afb5ceSopenharmony_ci		ev_idle_stop(loop, handle);
82d4afb5ceSopenharmony_ci
83d4afb5ceSopenharmony_ci	if (pt->destroy_self)
84d4afb5ceSopenharmony_ci		lws_context_destroy(pt->context);
85d4afb5ceSopenharmony_ci}
86d4afb5ceSopenharmony_ci
87d4afb5ceSopenharmony_cistatic void
88d4afb5ceSopenharmony_cilws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
89d4afb5ceSopenharmony_ci{
90d4afb5ceSopenharmony_ci	struct lws_io_watcher_libev *lws_io = lws_container_of(watcher,
91d4afb5ceSopenharmony_ci					struct lws_io_watcher_libev, watcher);
92d4afb5ceSopenharmony_ci	struct lws_context *context = lws_io->context;
93d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libev *ptpr;
94d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt;
95d4afb5ceSopenharmony_ci	struct lws_pollfd eventfd;
96d4afb5ceSopenharmony_ci	struct lws *wsi;
97d4afb5ceSopenharmony_ci
98d4afb5ceSopenharmony_ci	if (revents & EV_ERROR)
99d4afb5ceSopenharmony_ci		return;
100d4afb5ceSopenharmony_ci
101d4afb5ceSopenharmony_ci	eventfd.fd = watcher->fd;
102d4afb5ceSopenharmony_ci	eventfd.events = 0;
103d4afb5ceSopenharmony_ci	eventfd.revents = EV_NONE;
104d4afb5ceSopenharmony_ci
105d4afb5ceSopenharmony_ci	if (revents & EV_READ) {
106d4afb5ceSopenharmony_ci		eventfd.events |= LWS_POLLIN;
107d4afb5ceSopenharmony_ci		eventfd.revents |= LWS_POLLIN;
108d4afb5ceSopenharmony_ci	}
109d4afb5ceSopenharmony_ci	if (revents & EV_WRITE) {
110d4afb5ceSopenharmony_ci		eventfd.events |= LWS_POLLOUT;
111d4afb5ceSopenharmony_ci		eventfd.revents |= LWS_POLLOUT;
112d4afb5ceSopenharmony_ci	}
113d4afb5ceSopenharmony_ci
114d4afb5ceSopenharmony_ci	wsi = wsi_from_fd(context, watcher->fd);
115d4afb5ceSopenharmony_ci	pt = &context->pt[(int)wsi->tsi];
116d4afb5ceSopenharmony_ci	ptpr = pt_to_priv_ev(pt);
117d4afb5ceSopenharmony_ci
118d4afb5ceSopenharmony_ci	lws_service_fd_tsi(context, &eventfd, (int)wsi->tsi);
119d4afb5ceSopenharmony_ci
120d4afb5ceSopenharmony_ci	ev_idle_start(ptpr->io_loop, &ptpr->idle);
121d4afb5ceSopenharmony_ci}
122d4afb5ceSopenharmony_ci
123d4afb5ceSopenharmony_civoid
124d4afb5ceSopenharmony_cilws_ev_sigint_cb(struct ev_loop *loop, struct ev_signal *watcher, int revents)
125d4afb5ceSopenharmony_ci{
126d4afb5ceSopenharmony_ci	struct lws_context *context = watcher->data;
127d4afb5ceSopenharmony_ci
128d4afb5ceSopenharmony_ci	if (context->eventlib_signal_cb) {
129d4afb5ceSopenharmony_ci		context->eventlib_signal_cb((void *)watcher, watcher->signum);
130d4afb5ceSopenharmony_ci
131d4afb5ceSopenharmony_ci		return;
132d4afb5ceSopenharmony_ci	}
133d4afb5ceSopenharmony_ci	ev_break(loop, EVBREAK_ALL);
134d4afb5ceSopenharmony_ci}
135d4afb5ceSopenharmony_ci
136d4afb5ceSopenharmony_cistatic int
137d4afb5ceSopenharmony_cielops_listen_init_ev(struct lws_dll2 *d, void *user)
138d4afb5ceSopenharmony_ci{
139d4afb5ceSopenharmony_ci	struct lws *wsi = lws_container_of(d, struct lws, listen_list);
140d4afb5ceSopenharmony_ci	struct lws_context *context = (struct lws_context *)user;
141d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
142d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt);
143d4afb5ceSopenharmony_ci	struct lws_wsi_eventlibs_libev *w = wsi_to_priv_ev(wsi);
144d4afb5ceSopenharmony_ci	struct lws_vhost *vh = wsi->a.vhost;
145d4afb5ceSopenharmony_ci
146d4afb5ceSopenharmony_ci	w->w_read.context = context;
147d4afb5ceSopenharmony_ci	w->w_write.context = context;
148d4afb5ceSopenharmony_ci	vh_to_priv_ev(vh)->w_accept.context = context;
149d4afb5ceSopenharmony_ci
150d4afb5ceSopenharmony_ci	ev_io_init(&vh_to_priv_ev(vh)->w_accept.watcher,
151d4afb5ceSopenharmony_ci		   lws_accept_cb, wsi->desc.sockfd, EV_READ);
152d4afb5ceSopenharmony_ci	ev_io_start(ptpr->io_loop, &vh_to_priv_ev(vh)->w_accept.watcher);
153d4afb5ceSopenharmony_ci
154d4afb5ceSopenharmony_ci	return 0;
155d4afb5ceSopenharmony_ci}
156d4afb5ceSopenharmony_ci
157d4afb5ceSopenharmony_cistatic int
158d4afb5ceSopenharmony_cielops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
159d4afb5ceSopenharmony_ci{
160d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = &context->pt[tsi];
161d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt);
162d4afb5ceSopenharmony_ci	struct ev_signal *w_sigint = &ptpr->w_sigint.watcher;
163d4afb5ceSopenharmony_ci	struct ev_loop *loop = (struct ev_loop *)_loop;
164d4afb5ceSopenharmony_ci	const char *backend_name;
165d4afb5ceSopenharmony_ci	unsigned int backend;
166d4afb5ceSopenharmony_ci	int status = 0;
167d4afb5ceSopenharmony_ci
168d4afb5ceSopenharmony_ci	lwsl_cx_info(context, "loop %p", _loop);
169d4afb5ceSopenharmony_ci
170d4afb5ceSopenharmony_ci	ptpr->pt = pt;
171d4afb5ceSopenharmony_ci
172d4afb5ceSopenharmony_ci	if (!loop)
173d4afb5ceSopenharmony_ci		loop = ev_loop_new(0);
174d4afb5ceSopenharmony_ci	else
175d4afb5ceSopenharmony_ci		context->pt[tsi].event_loop_foreign = 1;
176d4afb5ceSopenharmony_ci
177d4afb5ceSopenharmony_ci	if (!loop) {
178d4afb5ceSopenharmony_ci		lwsl_cx_err(context, "creating event base failed");
179d4afb5ceSopenharmony_ci
180d4afb5ceSopenharmony_ci		return -1;
181d4afb5ceSopenharmony_ci	}
182d4afb5ceSopenharmony_ci
183d4afb5ceSopenharmony_ci	ptpr->io_loop = loop;
184d4afb5ceSopenharmony_ci
185d4afb5ceSopenharmony_ci	lws_vhost_foreach_listen_wsi(context, context, elops_listen_init_ev);
186d4afb5ceSopenharmony_ci
187d4afb5ceSopenharmony_ci	/* Register the signal watcher unless it's a foreign loop */
188d4afb5ceSopenharmony_ci	if (!context->pt[tsi].event_loop_foreign) {
189d4afb5ceSopenharmony_ci		ev_signal_init(w_sigint, lws_ev_sigint_cb, SIGINT);
190d4afb5ceSopenharmony_ci		w_sigint->data = context;
191d4afb5ceSopenharmony_ci		ev_signal_start(loop, w_sigint);
192d4afb5ceSopenharmony_ci	}
193d4afb5ceSopenharmony_ci
194d4afb5ceSopenharmony_ci	backend = ev_backend(loop);
195d4afb5ceSopenharmony_ci	switch (backend) {
196d4afb5ceSopenharmony_ci	case EVBACKEND_SELECT:
197d4afb5ceSopenharmony_ci		backend_name = "select";
198d4afb5ceSopenharmony_ci		break;
199d4afb5ceSopenharmony_ci	case EVBACKEND_POLL:
200d4afb5ceSopenharmony_ci		backend_name = "poll";
201d4afb5ceSopenharmony_ci		break;
202d4afb5ceSopenharmony_ci	case EVBACKEND_EPOLL:
203d4afb5ceSopenharmony_ci		backend_name = "epoll";
204d4afb5ceSopenharmony_ci		break;
205d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_EVBACKEND_LINUXAIO)
206d4afb5ceSopenharmony_ci       case EVBACKEND_LINUXAIO:
207d4afb5ceSopenharmony_ci               backend_name = "Linux AIO";
208d4afb5ceSopenharmony_ci               break;
209d4afb5ceSopenharmony_ci#endif
210d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_EVBACKEND_IOURING)
211d4afb5ceSopenharmony_ci       case EVBACKEND_IOURING:
212d4afb5ceSopenharmony_ci               backend_name = "Linux io_uring";
213d4afb5ceSopenharmony_ci               break;
214d4afb5ceSopenharmony_ci#endif
215d4afb5ceSopenharmony_ci       case EVBACKEND_KQUEUE:
216d4afb5ceSopenharmony_ci		backend_name = "kqueue";
217d4afb5ceSopenharmony_ci		break;
218d4afb5ceSopenharmony_ci	case EVBACKEND_DEVPOLL:
219d4afb5ceSopenharmony_ci		backend_name = "/dev/poll";
220d4afb5ceSopenharmony_ci		break;
221d4afb5ceSopenharmony_ci	case EVBACKEND_PORT:
222d4afb5ceSopenharmony_ci		backend_name = "Solaris 10 \"port\"";
223d4afb5ceSopenharmony_ci		break;
224d4afb5ceSopenharmony_ci	default:
225d4afb5ceSopenharmony_ci		backend_name = "Unknown libev backend";
226d4afb5ceSopenharmony_ci		break;
227d4afb5ceSopenharmony_ci	}
228d4afb5ceSopenharmony_ci
229d4afb5ceSopenharmony_ci	lwsl_cx_info(context, " libev backend: %s", backend_name);
230d4afb5ceSopenharmony_ci	(void)backend_name;
231d4afb5ceSopenharmony_ci
232d4afb5ceSopenharmony_ci	ev_timer_init(&ptpr->hrtimer, lws_ev_hrtimer_cb, 0, 0);
233d4afb5ceSopenharmony_ci	ptpr->hrtimer.data = pt;
234d4afb5ceSopenharmony_ci
235d4afb5ceSopenharmony_ci	ev_idle_init(&ptpr->idle, lws_ev_idle_cb);
236d4afb5ceSopenharmony_ci
237d4afb5ceSopenharmony_ci	return status;
238d4afb5ceSopenharmony_ci}
239d4afb5ceSopenharmony_ci
240d4afb5ceSopenharmony_cistatic int
241d4afb5ceSopenharmony_cielops_listen_destroy_ev(struct lws_dll2 *d, void *user)
242d4afb5ceSopenharmony_ci{
243d4afb5ceSopenharmony_ci	struct lws *wsi = lws_container_of(d, struct lws, listen_list);
244d4afb5ceSopenharmony_ci	struct lws_context *context = (struct lws_context *)user;
245d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
246d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt);
247d4afb5ceSopenharmony_ci	struct lws_vhost *vh = wsi->a.vhost;
248d4afb5ceSopenharmony_ci
249d4afb5ceSopenharmony_ci	ev_io_stop(ptpr->io_loop, &vh_to_priv_ev(vh)->w_accept.watcher);
250d4afb5ceSopenharmony_ci
251d4afb5ceSopenharmony_ci	return 0;
252d4afb5ceSopenharmony_ci}
253d4afb5ceSopenharmony_ci
254d4afb5ceSopenharmony_cistatic void
255d4afb5ceSopenharmony_cielops_destroy_pt_ev(struct lws_context *context, int tsi)
256d4afb5ceSopenharmony_ci{
257d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = &context->pt[tsi];
258d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt);
259d4afb5ceSopenharmony_ci
260d4afb5ceSopenharmony_ci	lws_vhost_foreach_listen_wsi(context, context, elops_listen_destroy_ev);
261d4afb5ceSopenharmony_ci
262d4afb5ceSopenharmony_ci	/* static assets */
263d4afb5ceSopenharmony_ci
264d4afb5ceSopenharmony_ci	ev_timer_stop(ptpr->io_loop, &ptpr->hrtimer);
265d4afb5ceSopenharmony_ci	ev_idle_stop(ptpr->io_loop, &ptpr->idle);
266d4afb5ceSopenharmony_ci
267d4afb5ceSopenharmony_ci	if (!pt->event_loop_foreign)
268d4afb5ceSopenharmony_ci		ev_signal_stop(ptpr->io_loop, &ptpr->w_sigint.watcher);
269d4afb5ceSopenharmony_ci}
270d4afb5ceSopenharmony_ci
271d4afb5ceSopenharmony_cistatic int
272d4afb5ceSopenharmony_cielops_init_context_ev(struct lws_context *context,
273d4afb5ceSopenharmony_ci		      const struct lws_context_creation_info *info)
274d4afb5ceSopenharmony_ci{
275d4afb5ceSopenharmony_ci	int n;
276d4afb5ceSopenharmony_ci
277d4afb5ceSopenharmony_ci	context->eventlib_signal_cb = info->signal_cb;
278d4afb5ceSopenharmony_ci
279d4afb5ceSopenharmony_ci	for (n = 0; n < context->count_threads; n++)
280d4afb5ceSopenharmony_ci		pt_to_priv_ev(&context->pt[n])->w_sigint.context = context;
281d4afb5ceSopenharmony_ci
282d4afb5ceSopenharmony_ci	return 0;
283d4afb5ceSopenharmony_ci}
284d4afb5ceSopenharmony_ci
285d4afb5ceSopenharmony_cistatic int
286d4afb5ceSopenharmony_cielops_accept_ev(struct lws *wsi)
287d4afb5ceSopenharmony_ci{
288d4afb5ceSopenharmony_ci	struct lws_wsi_eventlibs_libev *w = wsi_to_priv_ev(wsi);
289d4afb5ceSopenharmony_ci	int fd;
290d4afb5ceSopenharmony_ci
291d4afb5ceSopenharmony_ci	if (wsi->role_ops->file_handle)
292d4afb5ceSopenharmony_ci		fd = wsi->desc.filefd;
293d4afb5ceSopenharmony_ci	else
294d4afb5ceSopenharmony_ci		fd = wsi->desc.sockfd;
295d4afb5ceSopenharmony_ci
296d4afb5ceSopenharmony_ci	w->w_read.context = wsi->a.context;
297d4afb5ceSopenharmony_ci	w->w_write.context = wsi->a.context;
298d4afb5ceSopenharmony_ci
299d4afb5ceSopenharmony_ci	ev_io_init(&w->w_read.watcher, lws_accept_cb, fd, EV_READ);
300d4afb5ceSopenharmony_ci	ev_io_init(&w->w_write.watcher, lws_accept_cb, fd, EV_WRITE);
301d4afb5ceSopenharmony_ci
302d4afb5ceSopenharmony_ci	return 0;
303d4afb5ceSopenharmony_ci}
304d4afb5ceSopenharmony_ci
305d4afb5ceSopenharmony_cistatic void
306d4afb5ceSopenharmony_cielops_io_ev(struct lws *wsi, unsigned int flags)
307d4afb5ceSopenharmony_ci{
308d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
309d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt);
310d4afb5ceSopenharmony_ci	struct lws_wsi_eventlibs_libev *w = wsi_to_priv_ev(wsi);
311d4afb5ceSopenharmony_ci
312d4afb5ceSopenharmony_ci	lwsl_wsi_debug(wsi, "%s flags 0x%x %p %d", wsi->role_ops->name, flags,
313d4afb5ceSopenharmony_ci						   ptpr->io_loop,
314d4afb5ceSopenharmony_ci						   pt->is_destroyed);
315d4afb5ceSopenharmony_ci
316d4afb5ceSopenharmony_ci	if (!ptpr->io_loop || pt->is_destroyed)
317d4afb5ceSopenharmony_ci		return;
318d4afb5ceSopenharmony_ci
319d4afb5ceSopenharmony_ci	assert((flags & (LWS_EV_START | LWS_EV_STOP)) &&
320d4afb5ceSopenharmony_ci	       (flags & (LWS_EV_READ | LWS_EV_WRITE)));
321d4afb5ceSopenharmony_ci
322d4afb5ceSopenharmony_ci	if (flags & LWS_EV_START) {
323d4afb5ceSopenharmony_ci		if (flags & LWS_EV_WRITE)
324d4afb5ceSopenharmony_ci			ev_io_start(ptpr->io_loop, &w->w_write.watcher);
325d4afb5ceSopenharmony_ci		if (flags & LWS_EV_READ)
326d4afb5ceSopenharmony_ci			ev_io_start(ptpr->io_loop, &w->w_read.watcher);
327d4afb5ceSopenharmony_ci	} else {
328d4afb5ceSopenharmony_ci		if (flags & LWS_EV_WRITE)
329d4afb5ceSopenharmony_ci			ev_io_stop(ptpr->io_loop, &w->w_write.watcher);
330d4afb5ceSopenharmony_ci		if (flags & LWS_EV_READ)
331d4afb5ceSopenharmony_ci			ev_io_stop(ptpr->io_loop, &w->w_read.watcher);
332d4afb5ceSopenharmony_ci	}
333d4afb5ceSopenharmony_ci
334d4afb5ceSopenharmony_ci	if (pt->destroy_self)
335d4afb5ceSopenharmony_ci		lws_context_destroy(pt->context);
336d4afb5ceSopenharmony_ci}
337d4afb5ceSopenharmony_ci
338d4afb5ceSopenharmony_cistatic void
339d4afb5ceSopenharmony_cielops_run_pt_ev(struct lws_context *context, int tsi)
340d4afb5ceSopenharmony_ci{
341d4afb5ceSopenharmony_ci	if (pt_to_priv_ev(&context->pt[tsi])->io_loop)
342d4afb5ceSopenharmony_ci		ev_run(pt_to_priv_ev(&context->pt[tsi])->io_loop, 0);
343d4afb5ceSopenharmony_ci}
344d4afb5ceSopenharmony_ci
345d4afb5ceSopenharmony_cistatic int
346d4afb5ceSopenharmony_cielops_destroy_context2_ev(struct lws_context *context)
347d4afb5ceSopenharmony_ci{
348d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt;
349d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libev *ptpr;
350d4afb5ceSopenharmony_ci	int n, m;
351d4afb5ceSopenharmony_ci
352d4afb5ceSopenharmony_ci	for (n = 0; n < context->count_threads; n++) {
353d4afb5ceSopenharmony_ci		int budget = 1000;
354d4afb5ceSopenharmony_ci
355d4afb5ceSopenharmony_ci		pt = &context->pt[n];
356d4afb5ceSopenharmony_ci		ptpr = pt_to_priv_ev(pt);
357d4afb5ceSopenharmony_ci
358d4afb5ceSopenharmony_ci		/* only for internal loops... */
359d4afb5ceSopenharmony_ci
360d4afb5ceSopenharmony_ci		if (pt->event_loop_foreign || !ptpr->io_loop)
361d4afb5ceSopenharmony_ci			continue;
362d4afb5ceSopenharmony_ci
363d4afb5ceSopenharmony_ci		if (!context->evlib_finalize_destroy_after_int_loops_stop) {
364d4afb5ceSopenharmony_ci			ev_break(ptpr->io_loop, EVBREAK_ONE);
365d4afb5ceSopenharmony_ci			continue;
366d4afb5ceSopenharmony_ci		}
367d4afb5ceSopenharmony_ci		while (budget-- &&
368d4afb5ceSopenharmony_ci		       (m = ev_run(ptpr->io_loop, 0)))
369d4afb5ceSopenharmony_ci			;
370d4afb5ceSopenharmony_ci
371d4afb5ceSopenharmony_ci		ev_loop_destroy(ptpr->io_loop);
372d4afb5ceSopenharmony_ci	}
373d4afb5ceSopenharmony_ci
374d4afb5ceSopenharmony_ci	return 0;
375d4afb5ceSopenharmony_ci}
376d4afb5ceSopenharmony_ci
377d4afb5ceSopenharmony_cistatic int
378d4afb5ceSopenharmony_cielops_init_vhost_listen_wsi_ev(struct lws *wsi)
379d4afb5ceSopenharmony_ci{
380d4afb5ceSopenharmony_ci	struct lws_wsi_eventlibs_libev *w;
381d4afb5ceSopenharmony_ci	int fd;
382d4afb5ceSopenharmony_ci
383d4afb5ceSopenharmony_ci	if (!wsi) {
384d4afb5ceSopenharmony_ci		assert(0);
385d4afb5ceSopenharmony_ci		return 0;
386d4afb5ceSopenharmony_ci	}
387d4afb5ceSopenharmony_ci
388d4afb5ceSopenharmony_ci	w = wsi_to_priv_ev(wsi);
389d4afb5ceSopenharmony_ci	w->w_read.context = wsi->a.context;
390d4afb5ceSopenharmony_ci	w->w_write.context = wsi->a.context;
391d4afb5ceSopenharmony_ci
392d4afb5ceSopenharmony_ci	if (wsi->role_ops->file_handle)
393d4afb5ceSopenharmony_ci		fd = wsi->desc.filefd;
394d4afb5ceSopenharmony_ci	else
395d4afb5ceSopenharmony_ci		fd = wsi->desc.sockfd;
396d4afb5ceSopenharmony_ci
397d4afb5ceSopenharmony_ci	ev_io_init(&w->w_read.watcher, lws_accept_cb, fd, EV_READ);
398d4afb5ceSopenharmony_ci	//ev_io_init(&w->w_write.watcher, lws_accept_cb, fd, EV_WRITE);
399d4afb5ceSopenharmony_ci
400d4afb5ceSopenharmony_ci	elops_io_ev(wsi, LWS_EV_START | LWS_EV_READ);
401d4afb5ceSopenharmony_ci
402d4afb5ceSopenharmony_ci	return 0;
403d4afb5ceSopenharmony_ci}
404d4afb5ceSopenharmony_ci
405d4afb5ceSopenharmony_cistatic void
406d4afb5ceSopenharmony_cielops_destroy_wsi_ev(struct lws *wsi)
407d4afb5ceSopenharmony_ci{
408d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
409d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libev *ptpr = pt_to_priv_ev(pt);
410d4afb5ceSopenharmony_ci	struct lws_wsi_eventlibs_libev *w = wsi_to_priv_ev(wsi);
411d4afb5ceSopenharmony_ci
412d4afb5ceSopenharmony_ci	ev_io_stop(ptpr->io_loop, &w->w_read.watcher);
413d4afb5ceSopenharmony_ci	ev_io_stop(ptpr->io_loop, &w->w_write.watcher);
414d4afb5ceSopenharmony_ci}
415d4afb5ceSopenharmony_ci
416d4afb5ceSopenharmony_cistatic const struct lws_event_loop_ops event_loop_ops_ev = {
417d4afb5ceSopenharmony_ci	/* name */			"libev",
418d4afb5ceSopenharmony_ci	/* init_context */		elops_init_context_ev,
419d4afb5ceSopenharmony_ci	/* destroy_context1 */		NULL,
420d4afb5ceSopenharmony_ci	/* destroy_context2 */		elops_destroy_context2_ev,
421d4afb5ceSopenharmony_ci	/* init_vhost_listen_wsi */	elops_init_vhost_listen_wsi_ev,
422d4afb5ceSopenharmony_ci	/* init_pt */			elops_init_pt_ev,
423d4afb5ceSopenharmony_ci	/* wsi_logical_close */		NULL,
424d4afb5ceSopenharmony_ci	/* check_client_connect_ok */	NULL,
425d4afb5ceSopenharmony_ci	/* close_handle_manually */	NULL,
426d4afb5ceSopenharmony_ci	/* accept */			elops_accept_ev,
427d4afb5ceSopenharmony_ci	/* io */			elops_io_ev,
428d4afb5ceSopenharmony_ci	/* run_pt */			elops_run_pt_ev,
429d4afb5ceSopenharmony_ci	/* destroy_pt */		elops_destroy_pt_ev,
430d4afb5ceSopenharmony_ci	/* destroy wsi */		elops_destroy_wsi_ev,
431d4afb5ceSopenharmony_ci	/* foreign_thread */		NULL,
432d4afb5ceSopenharmony_ci
433d4afb5ceSopenharmony_ci	/* flags */			0,
434d4afb5ceSopenharmony_ci
435d4afb5ceSopenharmony_ci	/* evlib_size_ctx */	0,
436d4afb5ceSopenharmony_ci	/* evlib_size_pt */	sizeof(struct lws_pt_eventlibs_libev),
437d4afb5ceSopenharmony_ci	/* evlib_size_vh */	sizeof(struct lws_vh_eventlibs_libev),
438d4afb5ceSopenharmony_ci	/* evlib_size_wsi */	sizeof(struct lws_wsi_eventlibs_libev),
439d4afb5ceSopenharmony_ci};
440d4afb5ceSopenharmony_ci
441d4afb5ceSopenharmony_ci#if defined(LWS_WITH_EVLIB_PLUGINS)
442d4afb5ceSopenharmony_ciLWS_VISIBLE
443d4afb5ceSopenharmony_ci#endif
444d4afb5ceSopenharmony_ciconst lws_plugin_evlib_t evlib_ev = {
445d4afb5ceSopenharmony_ci	.hdr = {
446d4afb5ceSopenharmony_ci		"libev event loop",
447d4afb5ceSopenharmony_ci		"lws_evlib_plugin",
448d4afb5ceSopenharmony_ci		LWS_BUILD_HASH,
449d4afb5ceSopenharmony_ci		LWS_PLUGIN_API_MAGIC
450d4afb5ceSopenharmony_ci	},
451d4afb5ceSopenharmony_ci
452d4afb5ceSopenharmony_ci	.ops	= &event_loop_ops_ev
453d4afb5ceSopenharmony_ci};
454