libevent: update to use static plugins and work with new libevent2
[platform/upstream/libwebsockets.git] / lib / libevent.c
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation:
9  *  version 2.1 of the License.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *  MA  02110-1301  USA
20  */
21
22 #include "private-libwebsockets.h"
23
24 void lws_feature_status_libevent(struct lws_context_creation_info *info)
25 {
26   if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBEVENT))
27     lwsl_notice("libevent support compiled in and enabled\n");
28   else
29     lwsl_notice("libevent support compiled in but disabled\n");
30 }
31
32 static void
33 lws_event_cb(evutil_socket_t sock_fd, short revents, void *ctx)
34 {
35   struct lws_io_watcher *lws_io = (struct lws_io_watcher *)ctx;
36   struct lws_context *context = lws_io->context;
37   struct lws_pollfd eventfd;
38
39   if (revents & EV_TIMEOUT)
40     return;
41
42   /* !!! EV_CLOSED doesn't exist in libevent2 */
43 #if LIBEVENT_VERSION_NUMBER < 0x02000000
44   if (revents & EV_CLOSED)
45   {
46     event_del(lws_io->event_watcher);
47     event_free(lws_io->event_watcher);
48     return;
49   }
50 #endif
51
52   eventfd.fd = sock_fd;
53   eventfd.events = 0;
54   eventfd.revents = 0;
55   if (revents & EV_READ)
56   {
57     eventfd.events |= LWS_POLLIN;
58     eventfd.revents |= LWS_POLLIN;
59   }
60   if (revents & EV_WRITE)
61   {
62     eventfd.events |= LWS_POLLOUT;
63     eventfd.revents |= LWS_POLLOUT;
64   }
65   lws_service_fd(context, &eventfd);
66 }
67
68 LWS_VISIBLE void
69 lws_event_sigint_cb(evutil_socket_t sock_fd, short revents, void *ctx)
70 {
71   struct lws_context_per_thread *pt = ctx;
72   if (!pt->ev_loop_foreign)
73     event_base_loopbreak(pt->io_loop_event_base);
74 }
75
76 LWS_VISIBLE int
77 lws_event_sigint_cfg(struct lws_context *context, int use_event_sigint,
78       lws_event_signal_cb_t *cb)
79 {
80   context->use_ev_sigint = use_event_sigint;
81   if (cb)
82     context->lws_event_sigint_cb = cb;
83   else
84     context->lws_event_sigint_cb = &lws_event_sigint_cb;
85
86   return 0;
87 }
88
89 LWS_VISIBLE int
90 lws_event_initloop(struct lws_context *context, struct event_base *loop,
91     int tsi)
92 {
93   if (!loop)
94   {
95     context->pt[tsi].io_loop_event_base = event_base_new();
96   }
97   else
98   {
99     context->pt[tsi].ev_loop_foreign = 1;
100     context->pt[tsi].io_loop_event_base = loop;
101   }
102
103   /*
104    * Initialize all events with the listening sockets
105    * and register a callback for read operations
106    */
107   struct lws_vhost *vh = context->vhost_list;
108   while (vh)
109   {
110     if (vh->lserv_wsi)
111     {
112       vh->lserv_wsi->w_read.context = context;
113       vh->lserv_wsi->w_read.event_watcher = event_new(
114           loop,
115           vh->lserv_wsi->desc.sockfd,
116           (EV_READ | EV_PERSIST),
117           lws_event_cb,
118           &vh->lserv_wsi->w_read);
119       event_add(vh->lserv_wsi->w_read.event_watcher, NULL);
120     }
121     vh = vh->vhost_next;
122   }
123
124   /* Register the signal watcher unless the user says not to */
125   if (context->use_ev_sigint)
126   {
127     struct event *w_sigint = evsignal_new(loop, SIGINT,
128         context->lws_event_sigint_cb, &context->pt[tsi]);
129     context->pt[tsi].w_sigint.event_watcher = w_sigint;
130     event_add(w_sigint, NULL);
131   }
132
133   return 0;
134 }
135
136 void
137 lws_libevent_destroyloop(struct lws_context *context, int tsi)
138 {
139   if (!lws_check_opt(context->options, LWS_SERVER_OPTION_LIBEVENT))
140     return;
141
142   struct lws_context_per_thread *pt = &context->pt[tsi];
143   if (!pt->io_loop_event_base)
144     return;
145
146   /*
147    * Free all events with the listening sockets
148    */
149   struct lws_vhost *vh = context->vhost_list;
150   while (vh)
151   {
152     if (vh->lserv_wsi)
153     {
154       event_free(vh->lserv_wsi->w_read.event_watcher);
155       vh->lserv_wsi->w_read.event_watcher = NULL;
156     }
157     vh = vh->vhost_next;
158   }
159
160   if (context->use_ev_sigint)
161     event_free(pt->w_sigint.event_watcher);
162   if (!pt->ev_loop_foreign)
163     event_base_free(pt->io_loop_event_base);
164 }
165
166 LWS_VISIBLE void
167 lws_libevent_accept(struct lws *new_wsi, lws_sock_file_fd_type desc)
168 {
169   struct lws_context *context = lws_get_context(new_wsi);
170   if (!LWS_LIBEVENT_ENABLED(context))
171     return;
172
173   new_wsi->w_read.context = context;
174   new_wsi->w_write.context = context;
175
176   // Initialize the event
177   struct lws_context_per_thread *pt = &context->pt[(int)new_wsi->tsi];
178   int fd;
179   if (new_wsi->mode == LWSCM_RAW_FILEDESC)
180     fd = desc.filefd;
181   else
182     fd = desc.sockfd;
183   new_wsi->w_read.event_watcher = event_new(pt->io_loop_event_base, fd,
184       (EV_READ | EV_PERSIST), lws_event_cb, &new_wsi->w_read);
185   new_wsi->w_write.event_watcher = event_new(pt->io_loop_event_base, fd,
186       (EV_WRITE | EV_PERSIST), lws_event_cb, &new_wsi->w_write);
187 }
188
189 LWS_VISIBLE void
190 lws_libevent_io(struct lws *wsi, int flags)
191 {
192   struct lws_context *context = lws_get_context(wsi);
193
194   if (!LWS_LIBEVENT_ENABLED(context))
195     return;
196
197   struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
198   if (!pt->io_loop_event_base || context->being_destroyed)
199     return;
200
201   assert((flags & (LWS_EV_START | LWS_EV_STOP)) &&
202          (flags & (LWS_EV_READ | LWS_EV_WRITE)));
203
204   if (flags & LWS_EV_START)
205   {
206     if (flags & LWS_EV_WRITE)
207     {
208       event_add(wsi->w_write.event_watcher, NULL);
209     }
210     if (flags & LWS_EV_READ)
211     {
212       event_add(wsi->w_read.event_watcher, NULL);
213     }
214   }
215   else
216   {
217     if (flags & LWS_EV_WRITE)
218     {
219       event_del(wsi->w_write.event_watcher);
220     }
221     if (flags & LWS_EV_READ)
222     {
223       event_del(wsi->w_read.event_watcher);
224     }
225   }
226 }
227
228 LWS_VISIBLE int
229 lws_libevent_init_fd_table(struct lws_context *context)
230 {
231   if (!LWS_LIBEVENT_ENABLED(context))
232     return 0;
233
234   int n;
235   for (n = 0; n < context->count_threads; n++)
236   {
237     context->pt[n].w_sigint.context = context;
238   }
239
240   return 1;
241 }
242
243 LWS_VISIBLE void
244 lws_libevent_run(const struct lws_context *context, int tsi)
245 {
246   // Run/Dispatch the event_base loop
247   if (context->pt[tsi].io_loop_event_base && LWS_LIBEVENT_ENABLED(context))
248     event_base_dispatch(context->pt[tsi].io_loop_event_base);
249 }