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