1d4afb5ceSopenharmony_ci/*
2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation
3d4afb5ceSopenharmony_ci *
4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 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-libevent.h"
27d4afb5ceSopenharmony_ci
28d4afb5ceSopenharmony_ci#define pt_to_priv_event(_pt) ((struct lws_pt_eventlibs_libevent *)(_pt)->evlib_pt)
29d4afb5ceSopenharmony_ci#define wsi_to_priv_event(_w) ((struct lws_wsi_eventlibs_libevent *)(_w)->evlib_wsi)
30d4afb5ceSopenharmony_ci
31d4afb5ceSopenharmony_cistatic void
32d4afb5ceSopenharmony_cilws_event_hrtimer_cb(evutil_socket_t fd, short event, void *p)
33d4afb5ceSopenharmony_ci{
34d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = (struct lws_context_per_thread *)p;
35d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
36d4afb5ceSopenharmony_ci	struct timeval tv;
37d4afb5ceSopenharmony_ci	lws_usec_t us;
38d4afb5ceSopenharmony_ci
39d4afb5ceSopenharmony_ci	lws_pt_lock(pt, __func__);
40d4afb5ceSopenharmony_ci	us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
41d4afb5ceSopenharmony_ci				    lws_now_usecs());
42d4afb5ceSopenharmony_ci	if (us) {
43d4afb5ceSopenharmony_ci#if defined(__APPLE__)
44d4afb5ceSopenharmony_ci		tv.tv_sec = (int)(us / LWS_US_PER_SEC);
45d4afb5ceSopenharmony_ci		tv.tv_usec = (int)(us - (tv.tv_sec * LWS_US_PER_SEC));
46d4afb5ceSopenharmony_ci#else
47d4afb5ceSopenharmony_ci		tv.tv_sec = (long)(us / LWS_US_PER_SEC);
48d4afb5ceSopenharmony_ci		tv.tv_usec = (long)(us - (tv.tv_sec * LWS_US_PER_SEC));
49d4afb5ceSopenharmony_ci#endif
50d4afb5ceSopenharmony_ci		evtimer_add(ptpr->hrtimer, &tv);
51d4afb5ceSopenharmony_ci	}
52d4afb5ceSopenharmony_ci	lws_pt_unlock(pt);
53d4afb5ceSopenharmony_ci}
54d4afb5ceSopenharmony_ci
55d4afb5ceSopenharmony_cistatic void
56d4afb5ceSopenharmony_cilws_event_idle_timer_cb(evutil_socket_t fd, short event, void *p)
57d4afb5ceSopenharmony_ci{
58d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = (struct lws_context_per_thread *)p;
59d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
60d4afb5ceSopenharmony_ci	struct timeval tv;
61d4afb5ceSopenharmony_ci	lws_usec_t us;
62d4afb5ceSopenharmony_ci
63d4afb5ceSopenharmony_ci	if (pt->is_destroyed)
64d4afb5ceSopenharmony_ci		return;
65d4afb5ceSopenharmony_ci
66d4afb5ceSopenharmony_ci	lws_service_do_ripe_rxflow(pt);
67d4afb5ceSopenharmony_ci
68d4afb5ceSopenharmony_ci	/*
69d4afb5ceSopenharmony_ci	 * is there anybody with pending stuff that needs service forcing?
70d4afb5ceSopenharmony_ci	 */
71d4afb5ceSopenharmony_ci	if (!lws_service_adjust_timeout(pt->context, 1, pt->tid)) {
72d4afb5ceSopenharmony_ci		/* -1 timeout means just do forced service */
73d4afb5ceSopenharmony_ci		_lws_plat_service_forced_tsi(pt->context, pt->tid);
74d4afb5ceSopenharmony_ci		/* still somebody left who wants forced service? */
75d4afb5ceSopenharmony_ci		if (!lws_service_adjust_timeout(pt->context, 1, pt->tid)) {
76d4afb5ceSopenharmony_ci			/* yes... come back again later */
77d4afb5ceSopenharmony_ci
78d4afb5ceSopenharmony_ci			tv.tv_sec = 0;
79d4afb5ceSopenharmony_ci			tv.tv_usec = 1000;
80d4afb5ceSopenharmony_ci			evtimer_add(ptpr->idle_timer, &tv);
81d4afb5ceSopenharmony_ci
82d4afb5ceSopenharmony_ci			return;
83d4afb5ceSopenharmony_ci		}
84d4afb5ceSopenharmony_ci	}
85d4afb5ceSopenharmony_ci
86d4afb5ceSopenharmony_ci	/* account for hrtimer */
87d4afb5ceSopenharmony_ci
88d4afb5ceSopenharmony_ci	lws_pt_lock(pt, __func__);
89d4afb5ceSopenharmony_ci	us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
90d4afb5ceSopenharmony_ci				    lws_now_usecs());
91d4afb5ceSopenharmony_ci	if (us) {
92d4afb5ceSopenharmony_ci		tv.tv_sec = (suseconds_t)(us / LWS_US_PER_SEC);
93d4afb5ceSopenharmony_ci		tv.tv_usec = (suseconds_t)(us - (tv.tv_sec * LWS_US_PER_SEC));
94d4afb5ceSopenharmony_ci		evtimer_add(ptpr->hrtimer, &tv);
95d4afb5ceSopenharmony_ci	}
96d4afb5ceSopenharmony_ci	lws_pt_unlock(pt);
97d4afb5ceSopenharmony_ci
98d4afb5ceSopenharmony_ci	if (pt->destroy_self)
99d4afb5ceSopenharmony_ci		lws_context_destroy(pt->context);
100d4afb5ceSopenharmony_ci}
101d4afb5ceSopenharmony_ci
102d4afb5ceSopenharmony_cistatic void
103d4afb5ceSopenharmony_cilws_event_cb(evutil_socket_t sock_fd, short revents, void *ctx)
104d4afb5ceSopenharmony_ci{
105d4afb5ceSopenharmony_ci	struct lws_signal_watcher_libevent *lws_io =
106d4afb5ceSopenharmony_ci			(struct lws_signal_watcher_libevent *)ctx;
107d4afb5ceSopenharmony_ci	struct lws_context *context = lws_io->context;
108d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt;
109d4afb5ceSopenharmony_ci	struct lws_pollfd eventfd;
110d4afb5ceSopenharmony_ci	struct timeval tv;
111d4afb5ceSopenharmony_ci	struct lws *wsi;
112d4afb5ceSopenharmony_ci
113d4afb5ceSopenharmony_ci	if (revents & EV_TIMEOUT)
114d4afb5ceSopenharmony_ci		return;
115d4afb5ceSopenharmony_ci
116d4afb5ceSopenharmony_ci	/* !!! EV_CLOSED doesn't exist in libevent2 */
117d4afb5ceSopenharmony_ci#if LIBEVENT_VERSION_NUMBER < 0x02000000
118d4afb5ceSopenharmony_ci	if (revents & EV_CLOSED) {
119d4afb5ceSopenharmony_ci		event_del(lws_io->event.watcher);
120d4afb5ceSopenharmony_ci		event_free(lws_io->event.watcher);
121d4afb5ceSopenharmony_ci		return;
122d4afb5ceSopenharmony_ci	}
123d4afb5ceSopenharmony_ci#endif
124d4afb5ceSopenharmony_ci
125d4afb5ceSopenharmony_ci	eventfd.fd = sock_fd;
126d4afb5ceSopenharmony_ci	eventfd.events = 0;
127d4afb5ceSopenharmony_ci	eventfd.revents = 0;
128d4afb5ceSopenharmony_ci	if (revents & EV_READ) {
129d4afb5ceSopenharmony_ci		eventfd.events |= LWS_POLLIN;
130d4afb5ceSopenharmony_ci		eventfd.revents |= LWS_POLLIN;
131d4afb5ceSopenharmony_ci	}
132d4afb5ceSopenharmony_ci	if (revents & EV_WRITE) {
133d4afb5ceSopenharmony_ci		eventfd.events |= LWS_POLLOUT;
134d4afb5ceSopenharmony_ci		eventfd.revents |= LWS_POLLOUT;
135d4afb5ceSopenharmony_ci	}
136d4afb5ceSopenharmony_ci
137d4afb5ceSopenharmony_ci	wsi = wsi_from_fd(context, sock_fd);
138d4afb5ceSopenharmony_ci	if (!wsi)
139d4afb5ceSopenharmony_ci		return;
140d4afb5ceSopenharmony_ci
141d4afb5ceSopenharmony_ci	pt = &context->pt[(int)wsi->tsi];
142d4afb5ceSopenharmony_ci	if (pt->is_destroyed)
143d4afb5ceSopenharmony_ci		return;
144d4afb5ceSopenharmony_ci
145d4afb5ceSopenharmony_ci	lws_service_fd_tsi(context, &eventfd, wsi->tsi);
146d4afb5ceSopenharmony_ci
147d4afb5ceSopenharmony_ci	if (pt->destroy_self) {
148d4afb5ceSopenharmony_ci		lwsl_cx_notice(context, "pt destroy self coming true");
149d4afb5ceSopenharmony_ci		lws_context_destroy(pt->context);
150d4afb5ceSopenharmony_ci		return;
151d4afb5ceSopenharmony_ci	}
152d4afb5ceSopenharmony_ci
153d4afb5ceSopenharmony_ci	/* set the idle timer for 1ms ahead */
154d4afb5ceSopenharmony_ci
155d4afb5ceSopenharmony_ci	tv.tv_sec = 0;
156d4afb5ceSopenharmony_ci	tv.tv_usec = 1000;
157d4afb5ceSopenharmony_ci	evtimer_add(pt_to_priv_event(pt)->idle_timer, &tv);
158d4afb5ceSopenharmony_ci}
159d4afb5ceSopenharmony_ci
160d4afb5ceSopenharmony_civoid
161d4afb5ceSopenharmony_cilws_event_sigint_cb(evutil_socket_t sock_fd, short revents, void *ctx)
162d4afb5ceSopenharmony_ci{
163d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = ctx;
164d4afb5ceSopenharmony_ci	struct event *signal = pt_to_priv_event(pt)->w_sigint.watcher;
165d4afb5ceSopenharmony_ci
166d4afb5ceSopenharmony_ci	if (pt->context->eventlib_signal_cb) {
167d4afb5ceSopenharmony_ci		pt->context->eventlib_signal_cb((void *)(lws_intptr_t)sock_fd,
168d4afb5ceSopenharmony_ci						event_get_signal(signal));
169d4afb5ceSopenharmony_ci
170d4afb5ceSopenharmony_ci		return;
171d4afb5ceSopenharmony_ci	}
172d4afb5ceSopenharmony_ci	if (!pt->event_loop_foreign)
173d4afb5ceSopenharmony_ci		event_base_loopbreak(pt_to_priv_event(pt)->io_loop);
174d4afb5ceSopenharmony_ci}
175d4afb5ceSopenharmony_ci
176d4afb5ceSopenharmony_cistatic int
177d4afb5ceSopenharmony_cielops_listen_init_event(struct lws_dll2 *d, void *user)
178d4afb5ceSopenharmony_ci{
179d4afb5ceSopenharmony_ci	struct lws *wsi = lws_container_of(d, struct lws, listen_list);
180d4afb5ceSopenharmony_ci	struct lws_context *context = (struct lws_context *)user;
181d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
182d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
183d4afb5ceSopenharmony_ci	struct lws_io_watcher_libevent *w_read =
184d4afb5ceSopenharmony_ci					&(wsi_to_priv_event(wsi)->w_read);
185d4afb5ceSopenharmony_ci
186d4afb5ceSopenharmony_ci	w_read->context = context;
187d4afb5ceSopenharmony_ci	w_read->watcher = event_new(ptpr->io_loop, wsi->desc.sockfd,
188d4afb5ceSopenharmony_ci				(EV_READ | EV_PERSIST), lws_event_cb, w_read);
189d4afb5ceSopenharmony_ci	event_add(w_read->watcher, NULL);
190d4afb5ceSopenharmony_ci	w_read->set = 1;
191d4afb5ceSopenharmony_ci
192d4afb5ceSopenharmony_ci	return 0;
193d4afb5ceSopenharmony_ci}
194d4afb5ceSopenharmony_ci
195d4afb5ceSopenharmony_cistatic int
196d4afb5ceSopenharmony_cielops_init_pt_event(struct lws_context *context, void *_loop, int tsi)
197d4afb5ceSopenharmony_ci{
198d4afb5ceSopenharmony_ci	struct event_base *loop = (struct event_base *)_loop;
199d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = &context->pt[tsi];
200d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
201d4afb5ceSopenharmony_ci
202d4afb5ceSopenharmony_ci	lwsl_cx_info(context, "loop %p", _loop);
203d4afb5ceSopenharmony_ci
204d4afb5ceSopenharmony_ci	if (!loop)
205d4afb5ceSopenharmony_ci		loop = event_base_new();
206d4afb5ceSopenharmony_ci	else
207d4afb5ceSopenharmony_ci		context->pt[tsi].event_loop_foreign = 1;
208d4afb5ceSopenharmony_ci
209d4afb5ceSopenharmony_ci	if (!loop) {
210d4afb5ceSopenharmony_ci		lwsl_cx_err(context, "creating event base failed");
211d4afb5ceSopenharmony_ci
212d4afb5ceSopenharmony_ci		return -1;
213d4afb5ceSopenharmony_ci	}
214d4afb5ceSopenharmony_ci
215d4afb5ceSopenharmony_ci	ptpr->io_loop = loop;
216d4afb5ceSopenharmony_ci
217d4afb5ceSopenharmony_ci	lws_vhost_foreach_listen_wsi(context, context, elops_listen_init_event);
218d4afb5ceSopenharmony_ci
219d4afb5ceSopenharmony_ci	/* static event loop objects */
220d4afb5ceSopenharmony_ci
221d4afb5ceSopenharmony_ci	ptpr->hrtimer = event_new(loop, -1, EV_PERSIST,
222d4afb5ceSopenharmony_ci				      lws_event_hrtimer_cb, pt);
223d4afb5ceSopenharmony_ci
224d4afb5ceSopenharmony_ci	ptpr->idle_timer = event_new(loop, -1, 0,
225d4afb5ceSopenharmony_ci					 lws_event_idle_timer_cb, pt);
226d4afb5ceSopenharmony_ci	{
227d4afb5ceSopenharmony_ci		struct timeval tv;
228d4afb5ceSopenharmony_ci		tv.tv_sec = (long)0;
229d4afb5ceSopenharmony_ci		tv.tv_usec = (long)1000;
230d4afb5ceSopenharmony_ci		evtimer_add(ptpr->hrtimer, &tv);
231d4afb5ceSopenharmony_ci	}
232d4afb5ceSopenharmony_ci
233d4afb5ceSopenharmony_ci	/* Register the signal watcher unless it's a foreign loop */
234d4afb5ceSopenharmony_ci
235d4afb5ceSopenharmony_ci	if (pt->event_loop_foreign)
236d4afb5ceSopenharmony_ci		return 0;
237d4afb5ceSopenharmony_ci
238d4afb5ceSopenharmony_ci	ptpr->w_sigint.watcher = evsignal_new(loop, SIGINT,
239d4afb5ceSopenharmony_ci						  lws_event_sigint_cb, pt);
240d4afb5ceSopenharmony_ci	event_add(ptpr->w_sigint.watcher, NULL);
241d4afb5ceSopenharmony_ci
242d4afb5ceSopenharmony_ci	return 0;
243d4afb5ceSopenharmony_ci}
244d4afb5ceSopenharmony_ci
245d4afb5ceSopenharmony_cistatic int
246d4afb5ceSopenharmony_cielops_init_context_event(struct lws_context *context,
247d4afb5ceSopenharmony_ci			 const struct lws_context_creation_info *info)
248d4afb5ceSopenharmony_ci{
249d4afb5ceSopenharmony_ci	int n;
250d4afb5ceSopenharmony_ci
251d4afb5ceSopenharmony_ci	context->eventlib_signal_cb = info->signal_cb;
252d4afb5ceSopenharmony_ci
253d4afb5ceSopenharmony_ci	for (n = 0; n < context->count_threads; n++)
254d4afb5ceSopenharmony_ci		pt_to_priv_event(&context->pt[n])->w_sigint.context = context;
255d4afb5ceSopenharmony_ci
256d4afb5ceSopenharmony_ci	return 0;
257d4afb5ceSopenharmony_ci}
258d4afb5ceSopenharmony_ci
259d4afb5ceSopenharmony_cistatic int
260d4afb5ceSopenharmony_cielops_accept_event(struct lws *wsi)
261d4afb5ceSopenharmony_ci{
262d4afb5ceSopenharmony_ci	struct lws_context *context = lws_get_context(wsi);
263d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt;
264d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libevent *ptpr;
265d4afb5ceSopenharmony_ci	struct lws_wsi_eventlibs_libevent *wpr = wsi_to_priv_event(wsi);
266d4afb5ceSopenharmony_ci       evutil_socket_t fd;
267d4afb5ceSopenharmony_ci
268d4afb5ceSopenharmony_ci	wpr->w_read.context = context;
269d4afb5ceSopenharmony_ci	wpr->w_write.context = context;
270d4afb5ceSopenharmony_ci
271d4afb5ceSopenharmony_ci	// Initialize the event
272d4afb5ceSopenharmony_ci	pt = &context->pt[(int)wsi->tsi];
273d4afb5ceSopenharmony_ci	ptpr = pt_to_priv_event(pt);
274d4afb5ceSopenharmony_ci
275d4afb5ceSopenharmony_ci	if (wsi->role_ops->file_handle)
276d4afb5ceSopenharmony_ci               fd = (evutil_socket_t)(ev_intptr_t) wsi->desc.filefd;
277d4afb5ceSopenharmony_ci	else
278d4afb5ceSopenharmony_ci		fd = wsi->desc.sockfd;
279d4afb5ceSopenharmony_ci
280d4afb5ceSopenharmony_ci	wpr->w_read.watcher = event_new(ptpr->io_loop, fd,
281d4afb5ceSopenharmony_ci			(EV_READ | EV_PERSIST), lws_event_cb, &wpr->w_read);
282d4afb5ceSopenharmony_ci	wpr->w_write.watcher = event_new(ptpr->io_loop, fd,
283d4afb5ceSopenharmony_ci			(EV_WRITE | EV_PERSIST), lws_event_cb, &wpr->w_write);
284d4afb5ceSopenharmony_ci
285d4afb5ceSopenharmony_ci	return 0;
286d4afb5ceSopenharmony_ci}
287d4afb5ceSopenharmony_ci
288d4afb5ceSopenharmony_cistatic void
289d4afb5ceSopenharmony_cielops_io_event(struct lws *wsi, unsigned int flags)
290d4afb5ceSopenharmony_ci{
291d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
292d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
293d4afb5ceSopenharmony_ci	struct lws_wsi_eventlibs_libevent *wpr = wsi_to_priv_event(wsi);
294d4afb5ceSopenharmony_ci
295d4afb5ceSopenharmony_ci	if (!ptpr->io_loop || wsi->a.context->being_destroyed ||
296d4afb5ceSopenharmony_ci	    pt->is_destroyed)
297d4afb5ceSopenharmony_ci		return;
298d4afb5ceSopenharmony_ci
299d4afb5ceSopenharmony_ci	assert((flags & (LWS_EV_START | LWS_EV_STOP)) &&
300d4afb5ceSopenharmony_ci	       (flags & (LWS_EV_READ | LWS_EV_WRITE)));
301d4afb5ceSopenharmony_ci
302d4afb5ceSopenharmony_ci	if (flags & LWS_EV_START) {
303d4afb5ceSopenharmony_ci		if ((flags & LWS_EV_WRITE) && !wpr->w_write.set) {
304d4afb5ceSopenharmony_ci			event_add(wpr->w_write.watcher, NULL);
305d4afb5ceSopenharmony_ci			wpr->w_write.set = 1;
306d4afb5ceSopenharmony_ci		}
307d4afb5ceSopenharmony_ci
308d4afb5ceSopenharmony_ci		if ((flags & LWS_EV_READ) && !wpr->w_read.set) {
309d4afb5ceSopenharmony_ci			event_add(wpr->w_read.watcher, NULL);
310d4afb5ceSopenharmony_ci			wpr->w_read.set = 1;
311d4afb5ceSopenharmony_ci		}
312d4afb5ceSopenharmony_ci	} else {
313d4afb5ceSopenharmony_ci		if ((flags & LWS_EV_WRITE) && wpr->w_write.set) {
314d4afb5ceSopenharmony_ci			event_del(wpr->w_write.watcher);
315d4afb5ceSopenharmony_ci			wpr->w_write.set = 0;
316d4afb5ceSopenharmony_ci		}
317d4afb5ceSopenharmony_ci
318d4afb5ceSopenharmony_ci		if ((flags & LWS_EV_READ) && wpr->w_read.set) {
319d4afb5ceSopenharmony_ci			event_del(wpr->w_read.watcher);
320d4afb5ceSopenharmony_ci			wpr->w_read.set = 0;
321d4afb5ceSopenharmony_ci		}
322d4afb5ceSopenharmony_ci	}
323d4afb5ceSopenharmony_ci}
324d4afb5ceSopenharmony_ci
325d4afb5ceSopenharmony_cistatic void
326d4afb5ceSopenharmony_cielops_run_pt_event(struct lws_context *context, int tsi)
327d4afb5ceSopenharmony_ci{
328d4afb5ceSopenharmony_ci	/* Run / Dispatch the event_base loop */
329d4afb5ceSopenharmony_ci	if (pt_to_priv_event(&context->pt[tsi])->io_loop)
330d4afb5ceSopenharmony_ci		event_base_dispatch(
331d4afb5ceSopenharmony_ci			pt_to_priv_event(&context->pt[tsi])->io_loop);
332d4afb5ceSopenharmony_ci}
333d4afb5ceSopenharmony_ci
334d4afb5ceSopenharmony_cistatic int
335d4afb5ceSopenharmony_cielops_listen_destroy_event(struct lws_dll2 *d, void *user)
336d4afb5ceSopenharmony_ci{
337d4afb5ceSopenharmony_ci	struct lws *wsi = lws_container_of(d, struct lws, listen_list);
338d4afb5ceSopenharmony_ci	struct lws_wsi_eventlibs_libevent *w = wsi_to_priv_event(wsi);
339d4afb5ceSopenharmony_ci
340d4afb5ceSopenharmony_ci	event_free(w->w_read.watcher);
341d4afb5ceSopenharmony_ci	w->w_read.watcher = NULL;
342d4afb5ceSopenharmony_ci	event_free(w->w_write.watcher);
343d4afb5ceSopenharmony_ci	w->w_write.watcher = NULL;
344d4afb5ceSopenharmony_ci
345d4afb5ceSopenharmony_ci	return 0;
346d4afb5ceSopenharmony_ci}
347d4afb5ceSopenharmony_ci
348d4afb5ceSopenharmony_cistatic void
349d4afb5ceSopenharmony_cielops_destroy_pt_event(struct lws_context *context, int tsi)
350d4afb5ceSopenharmony_ci{
351d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = &context->pt[tsi];
352d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libevent *ptpr = pt_to_priv_event(pt);
353d4afb5ceSopenharmony_ci
354d4afb5ceSopenharmony_ci	if (!ptpr->io_loop)
355d4afb5ceSopenharmony_ci		return;
356d4afb5ceSopenharmony_ci
357d4afb5ceSopenharmony_ci	lws_vhost_foreach_listen_wsi(context, context, elops_listen_destroy_event);
358d4afb5ceSopenharmony_ci
359d4afb5ceSopenharmony_ci	event_free(ptpr->hrtimer);
360d4afb5ceSopenharmony_ci	event_free(ptpr->idle_timer);
361d4afb5ceSopenharmony_ci
362d4afb5ceSopenharmony_ci	if (!pt->event_loop_foreign) {
363d4afb5ceSopenharmony_ci		event_del(ptpr->w_sigint.watcher);
364d4afb5ceSopenharmony_ci		event_free(ptpr->w_sigint.watcher);
365d4afb5ceSopenharmony_ci		event_base_loopexit(ptpr->io_loop, NULL);
366d4afb5ceSopenharmony_ci	//	event_base_free(pt->event.io_loop);
367d4afb5ceSopenharmony_ci	//	pt->event.io_loop = NULL;
368d4afb5ceSopenharmony_ci		lwsl_cx_notice(context, "set to exit loop");
369d4afb5ceSopenharmony_ci	}
370d4afb5ceSopenharmony_ci}
371d4afb5ceSopenharmony_ci
372d4afb5ceSopenharmony_cistatic void
373d4afb5ceSopenharmony_cielops_destroy_wsi_event(struct lws *wsi)
374d4afb5ceSopenharmony_ci{
375d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt;
376d4afb5ceSopenharmony_ci	struct lws_wsi_eventlibs_libevent *w;
377d4afb5ceSopenharmony_ci
378d4afb5ceSopenharmony_ci	if (!wsi)
379d4afb5ceSopenharmony_ci		return;
380d4afb5ceSopenharmony_ci
381d4afb5ceSopenharmony_ci	pt = &wsi->a.context->pt[(int)wsi->tsi];
382d4afb5ceSopenharmony_ci	if (pt->is_destroyed)
383d4afb5ceSopenharmony_ci		return;
384d4afb5ceSopenharmony_ci
385d4afb5ceSopenharmony_ci	w = wsi_to_priv_event(wsi);
386d4afb5ceSopenharmony_ci
387d4afb5ceSopenharmony_ci	if (w->w_read.watcher) {
388d4afb5ceSopenharmony_ci		event_free(w->w_read.watcher);
389d4afb5ceSopenharmony_ci		w->w_read.watcher = NULL;
390d4afb5ceSopenharmony_ci	}
391d4afb5ceSopenharmony_ci
392d4afb5ceSopenharmony_ci	if (w->w_write.watcher) {
393d4afb5ceSopenharmony_ci		event_free(w->w_write.watcher);
394d4afb5ceSopenharmony_ci		w->w_write.watcher = NULL;
395d4afb5ceSopenharmony_ci	}
396d4afb5ceSopenharmony_ci}
397d4afb5ceSopenharmony_ci
398d4afb5ceSopenharmony_cistatic int
399d4afb5ceSopenharmony_cielops_wsi_logical_close_event(struct lws *wsi)
400d4afb5ceSopenharmony_ci{
401d4afb5ceSopenharmony_ci	elops_destroy_wsi_event(wsi);
402d4afb5ceSopenharmony_ci
403d4afb5ceSopenharmony_ci	return 0;
404d4afb5ceSopenharmony_ci}
405d4afb5ceSopenharmony_ci
406d4afb5ceSopenharmony_cistatic int
407d4afb5ceSopenharmony_cielops_init_vhost_listen_wsi_event(struct lws *wsi)
408d4afb5ceSopenharmony_ci{
409d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt;
410d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libevent *ptpr;
411d4afb5ceSopenharmony_ci	struct lws_wsi_eventlibs_libevent *w;
412d4afb5ceSopenharmony_ci       evutil_socket_t fd;
413d4afb5ceSopenharmony_ci
414d4afb5ceSopenharmony_ci	if (!wsi) {
415d4afb5ceSopenharmony_ci		assert(0);
416d4afb5ceSopenharmony_ci		return 0;
417d4afb5ceSopenharmony_ci	}
418d4afb5ceSopenharmony_ci
419d4afb5ceSopenharmony_ci	w = wsi_to_priv_event(wsi);
420d4afb5ceSopenharmony_ci
421d4afb5ceSopenharmony_ci	w->w_read.context = wsi->a.context;
422d4afb5ceSopenharmony_ci	w->w_write.context = wsi->a.context;
423d4afb5ceSopenharmony_ci
424d4afb5ceSopenharmony_ci	pt = &wsi->a.context->pt[(int)wsi->tsi];
425d4afb5ceSopenharmony_ci	ptpr = pt_to_priv_event(pt);
426d4afb5ceSopenharmony_ci
427d4afb5ceSopenharmony_ci	if (wsi->role_ops->file_handle)
428d4afb5ceSopenharmony_ci               fd = (evutil_socket_t) wsi->desc.filefd;
429d4afb5ceSopenharmony_ci	else
430d4afb5ceSopenharmony_ci		fd = wsi->desc.sockfd;
431d4afb5ceSopenharmony_ci
432d4afb5ceSopenharmony_ci	w->w_read.watcher = event_new(ptpr->io_loop, fd, (EV_READ | EV_PERSIST),
433d4afb5ceSopenharmony_ci				      lws_event_cb, &w->w_read);
434d4afb5ceSopenharmony_ci	w->w_write.watcher = event_new(ptpr->io_loop, fd,
435d4afb5ceSopenharmony_ci				       (EV_WRITE | EV_PERSIST),
436d4afb5ceSopenharmony_ci				       lws_event_cb, &w->w_write);
437d4afb5ceSopenharmony_ci
438d4afb5ceSopenharmony_ci	elops_io_event(wsi, LWS_EV_START | LWS_EV_READ);
439d4afb5ceSopenharmony_ci
440d4afb5ceSopenharmony_ci	return 0;
441d4afb5ceSopenharmony_ci}
442d4afb5ceSopenharmony_ci
443d4afb5ceSopenharmony_cistatic int
444d4afb5ceSopenharmony_cielops_destroy_context2_event(struct lws_context *context)
445d4afb5ceSopenharmony_ci{
446d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt;
447d4afb5ceSopenharmony_ci	struct lws_pt_eventlibs_libevent *ptpr;
448d4afb5ceSopenharmony_ci	int n, m;
449d4afb5ceSopenharmony_ci
450d4afb5ceSopenharmony_ci	for (n = 0; n < context->count_threads; n++) {
451d4afb5ceSopenharmony_ci		int budget = 1000;
452d4afb5ceSopenharmony_ci
453d4afb5ceSopenharmony_ci		pt = &context->pt[n];
454d4afb5ceSopenharmony_ci		ptpr = pt_to_priv_event(pt);
455d4afb5ceSopenharmony_ci
456d4afb5ceSopenharmony_ci		/* only for internal loops... */
457d4afb5ceSopenharmony_ci
458d4afb5ceSopenharmony_ci		if (pt->event_loop_foreign || !ptpr->io_loop)
459d4afb5ceSopenharmony_ci			continue;
460d4afb5ceSopenharmony_ci
461d4afb5ceSopenharmony_ci		if (!context->evlib_finalize_destroy_after_int_loops_stop) {
462d4afb5ceSopenharmony_ci			event_base_loopexit(ptpr->io_loop, NULL);
463d4afb5ceSopenharmony_ci			continue;
464d4afb5ceSopenharmony_ci		}
465d4afb5ceSopenharmony_ci		while (budget-- &&
466d4afb5ceSopenharmony_ci		       (m = event_base_loop(ptpr->io_loop, EVLOOP_NONBLOCK)))
467d4afb5ceSopenharmony_ci			;
468d4afb5ceSopenharmony_ci
469d4afb5ceSopenharmony_ci		lwsl_cx_info(context, "event_base_free");
470d4afb5ceSopenharmony_ci
471d4afb5ceSopenharmony_ci		event_base_free(ptpr->io_loop);
472d4afb5ceSopenharmony_ci		ptpr->io_loop = NULL;
473d4afb5ceSopenharmony_ci	}
474d4afb5ceSopenharmony_ci
475d4afb5ceSopenharmony_ci	return 0;
476d4afb5ceSopenharmony_ci}
477d4afb5ceSopenharmony_ci
478d4afb5ceSopenharmony_cistatic const struct lws_event_loop_ops event_loop_ops_event = {
479d4afb5ceSopenharmony_ci	/* name */			"libevent",
480d4afb5ceSopenharmony_ci	/* init_context */		elops_init_context_event,
481d4afb5ceSopenharmony_ci	/* destroy_context1 */		NULL,
482d4afb5ceSopenharmony_ci	/* destroy_context2 */		elops_destroy_context2_event,
483d4afb5ceSopenharmony_ci	/* init_vhost_listen_wsi */	elops_init_vhost_listen_wsi_event,
484d4afb5ceSopenharmony_ci	/* init_pt */			elops_init_pt_event,
485d4afb5ceSopenharmony_ci	/* wsi_logical_close */		elops_wsi_logical_close_event,
486d4afb5ceSopenharmony_ci	/* check_client_connect_ok */	NULL,
487d4afb5ceSopenharmony_ci	/* close_handle_manually */	NULL,
488d4afb5ceSopenharmony_ci	/* accept */			elops_accept_event,
489d4afb5ceSopenharmony_ci	/* io */			elops_io_event,
490d4afb5ceSopenharmony_ci	/* run_pt */			elops_run_pt_event,
491d4afb5ceSopenharmony_ci	/* destroy_pt */		elops_destroy_pt_event,
492d4afb5ceSopenharmony_ci	/* destroy wsi */		elops_destroy_wsi_event,
493d4afb5ceSopenharmony_ci	/* foreign_thread */		NULL,
494d4afb5ceSopenharmony_ci
495d4afb5ceSopenharmony_ci	/* flags */			0,
496d4afb5ceSopenharmony_ci
497d4afb5ceSopenharmony_ci	/* evlib_size_ctx */	0,
498d4afb5ceSopenharmony_ci	/* evlib_size_pt */	sizeof(struct lws_pt_eventlibs_libevent),
499d4afb5ceSopenharmony_ci	/* evlib_size_vh */	0,
500d4afb5ceSopenharmony_ci	/* evlib_size_wsi */	sizeof(struct lws_wsi_eventlibs_libevent),
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_event = {
507d4afb5ceSopenharmony_ci	.hdr = {
508d4afb5ceSopenharmony_ci		"libevent 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_event
515d4afb5ceSopenharmony_ci};
516