fixed ssl.c bug when ssl backend returns IO_BLOCKED but IO engine doesn't get informe...
[ircu2.10.12-pk.git] / ircd / engine_kqueue.c
1 /*
2  * IRC - Internet Relay Chat, ircd/engine_kqueue.c
3  * Copyright (C) 2001 Kevin L. Mitchell <klmitch@mit.edu>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 1, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /** @file
20  * @brief FreeBSD kqueue()/kevent() event engine.
21  * @version $Id: engine_kqueue.c 1335 2005-03-23 00:25:16Z entrope $
22  */
23 #include "config.h"
24
25 #include "ircd_events.h"
26
27 #include "ircd.h"
28 #include "ircd_alloc.h"
29 #include "ircd_features.h"
30 #include "ircd_log.h"
31 #include "s_debug.h"
32
33 /* #include <assert.h> -- Now using assert in ircd_log.h */
34 #include <errno.h>
35 #include <signal.h>
36 #include <sys/types.h>
37 #include <sys/event.h>
38 #include <sys/socket.h>
39 #include <sys/time.h>
40 #include <time.h>
41 #include <unistd.h>
42
43 #define KQUEUE_ERROR_THRESHOLD  20      /**< after 20 kqueue errors, restart */
44 #define ERROR_EXPIRE_TIME       3600    /**< expire errors after an hour */
45
46 /** Array of active Socket structures, indexed by file descriptor. */
47 static struct Socket** sockList;
48 /** Maximum file descriptor supported, plus one. */
49 static int kqueue_max;
50 /** File descriptor for kqueue pseudo-file. */
51 static int kqueue_id;
52
53 /** Number of recent errors from kqueue. */
54 static int errors = 0;
55 /** Periodic timer to forget errors. */
56 static struct Timer clear_error;
57
58 /** Decrement the error count (once per hour).
59  * @param[in] ev Expired timer event (ignored).
60  */
61 static void
62 error_clear(struct Event* ev)
63 {
64   if (!--errors) /* remove timer when error count reaches 0 */
65     timer_del(ev_timer(ev));
66 }
67
68 /** Initialize the kqueue engine.
69  * @param[in] max_sockets Maximum number of file descriptors to support.
70  * @return Non-zero on success, or zero on failure.
71  */
72 static int
73 engine_init(int max_sockets)
74 {
75   int i;
76
77   if ((kqueue_id = kqueue()) < 0) { /* initialize... */
78     log_write(LS_SYSTEM, L_WARNING, 0,
79               "kqueue() engine cannot initialize: %m");
80     return 0;
81   }
82
83   /* allocate necessary memory */
84   sockList = (struct Socket**) MyMalloc(sizeof(struct Socket*) * max_sockets);
85
86   /* initialize the data */
87   for (i = 0; i < max_sockets; i++)
88     sockList[i] = 0;
89
90   kqueue_max = max_sockets; /* number of sockets allocated */
91
92   return 1; /* success! */
93 }
94
95 /** Add a signal to the event engine.
96  * @param[in] sig Signal to add to engine.
97  */
98 static void
99 engine_signal(struct Signal* sig)
100 {
101   struct kevent sigevent;
102   struct sigaction act;
103
104   assert(0 != signal);
105
106   Debug((DEBUG_ENGINE, "kqueue: Adding filter for signal %d [%p]",
107          sig_signal(sig), sig));
108
109   sigevent.ident = sig_signal(sig); /* set up the kqueue event */
110   sigevent.filter = EVFILT_SIGNAL; /* looking for signals... */
111   sigevent.flags = EV_ADD | EV_ENABLE; /* add and enable it */
112   sigevent.fflags = 0;
113   sigevent.data = 0;
114   sigevent.udata = sig; /* store our user data */
115
116   if (kevent(kqueue_id, &sigevent, 1, 0, 0, 0) < 0) { /* add event */
117     log_write(LS_SYSTEM, L_WARNING, 0, "Unable to trap signal %d",
118               sig_signal(sig));
119     return;
120   }
121
122   act.sa_handler = SIG_IGN; /* ignore the signal */
123   act.sa_flags = 0;
124   sigemptyset(&act.sa_mask);
125   sigaction(sig_signal(sig), &act, 0);
126 }
127
128 /** Figure out what events go with a given state.
129  * @param[in] state %Socket state to consider.
130  * @param[in] events User-specified preferred event set.
131  * @return Actual set of preferred events.
132  */
133 static unsigned int
134 state_to_events(enum SocketState state, unsigned int events)
135 {
136   switch (state) {
137   case SS_CONNECTING: /* connecting socket */
138     return SOCK_EVENT_WRITABLE;
139     break;
140
141   case SS_LISTENING: /* listening socket */
142   case SS_NOTSOCK: /* our signal socket--just in case */
143     return SOCK_EVENT_READABLE;
144     break;
145
146   case SS_CONNECTED: case SS_DATAGRAM: case SS_CONNECTDG:
147     return events; /* ordinary socket */
148     break;
149   }
150
151   /*NOTREACHED*/
152   return 0;
153 }
154
155 /** Activate kqueue filters as appropriate.
156  * @param[in] sock Socket structure to operate on.
157  * @param[in] clear Set of interest events to clear from socket.
158  * @param[in] set Set of interest events to set on socket.
159  */
160 static void
161 set_or_clear(struct Socket* sock, unsigned int clear, unsigned int set)
162 {
163   int i = 0;
164   struct kevent chglist[2];
165
166   assert(0 != sock);
167   assert(-1 < s_fd(sock));
168
169   if ((clear ^ set) & SOCK_EVENT_READABLE) { /* readable has changed */
170     chglist[i].ident = s_fd(sock); /* set up the change list */
171     chglist[i].filter = EVFILT_READ; /* readable filter */
172     chglist[i].flags = EV_ADD; /* adding it */
173     chglist[i].fflags = 0;
174     chglist[i].data = 0;
175     chglist[i].udata = 0; /* I love udata, but it can't really be used here */
176
177     if (set & SOCK_EVENT_READABLE) /* it's set */
178       chglist[i].flags |= EV_ENABLE;
179     else /* clear it */
180       chglist[i].flags |= EV_DISABLE;
181
182     i++; /* advance to next element */
183   }
184
185   if ((clear ^ set) & SOCK_EVENT_WRITABLE) { /* writable has changed */
186     chglist[i].ident = s_fd(sock); /* set up the change list */
187     chglist[i].filter = EVFILT_WRITE; /* writable filter */
188     chglist[i].flags = EV_ADD; /* adding it */
189     chglist[i].fflags = 0;
190     chglist[i].data = 0;
191     chglist[i].udata = 0;
192
193     if (set & SOCK_EVENT_WRITABLE) /* it's set */
194       chglist[i].flags |= EV_ENABLE;
195     else /* clear it */
196       chglist[i].flags |= EV_DISABLE;
197
198     i++; /* advance count... */
199   }
200
201   if (kevent(kqueue_id, chglist, i, 0, 0, 0) < 0 && errno != EBADF)
202     event_generate(ET_ERROR, sock, errno); /* report error */
203 }
204
205 /** Add a socket to the event engine.
206  * @param[in] sock Socket to add to engine.
207  * @return Non-zero on success, or zero on error.
208  */
209 static int
210 engine_add(struct Socket* sock)
211 {
212   assert(0 != sock);
213   assert(0 == sockList[s_fd(sock)]);
214
215   /* bounds-check... */
216   if (sock->s_fd >= kqueue_max) {
217     log_write(LS_SYSTEM, L_ERROR, 0,
218               "Attempt to add socket %d (> %d) to event engine", s_fd(sock),
219               kqueue_max);
220     return 0;
221   }
222
223   sockList[s_fd(sock)] = sock; /* add to list */
224
225   Debug((DEBUG_ENGINE, "kqueue: Adding socket %d [%p], state %s, to engine",
226          s_fd(sock), sock, state_to_name(s_state(sock))));
227
228   /* Add socket to queue */
229   set_or_clear(sock, 0, state_to_events(s_state(sock), s_events(sock)));
230
231   return 1; /* success */
232 }
233
234 /** Handle state transition for a socket.
235  * @param[in] sock Socket changing state.
236  * @param[in] new_state New state for socket.
237  */
238 static void
239 engine_state(struct Socket* sock, enum SocketState new_state)
240 {
241   assert(0 != sock);
242   assert(sock == sockList[s_fd(sock)]);
243
244   Debug((DEBUG_ENGINE, "kqueue: Changing state for socket %p to %s", sock,
245          state_to_name(new_state)));
246
247   /* set the correct events */
248   set_or_clear(sock,
249                state_to_events(s_state(sock), s_events(sock)), /* old state */
250                state_to_events(new_state, s_events(sock))); /* new state */
251
252 }
253
254 /** Handle change to preferred socket events.
255  * @param[in] sock Socket getting new interest list.
256  * @param[in] new_events New set of interesting events for socket.
257  */
258 static void
259 engine_events(struct Socket* sock, unsigned int new_events)
260 {
261   assert(0 != sock);
262   assert(sock == sockList[s_fd(sock)]);
263
264   Debug((DEBUG_ENGINE, "kqueue: Changing event mask for socket %p to [%s]",
265          sock, sock_flags(new_events)));
266
267   /* set the correct events */
268   set_or_clear(sock,
269                state_to_events(s_state(sock), s_events(sock)), /* old events */
270                state_to_events(s_state(sock), new_events)); /* new events */
271 }
272
273 /** Remove a socket from the event engine.
274  * @param[in] sock Socket being destroyed.
275  */
276 static void
277 engine_delete(struct Socket* sock)
278 {
279   struct kevent dellist[2];
280
281   assert(0 != sock);
282   assert(sock == sockList[s_fd(sock)]);
283
284   Debug((DEBUG_ENGINE, "kqueue: Deleting socket %d [%p], state %s",
285          s_fd(sock), sock, state_to_name(s_state(sock))));
286
287   dellist[0].ident = s_fd(sock); /* set up the delete list */
288   dellist[0].filter = EVFILT_READ; /* readable filter */
289   dellist[0].flags = EV_DELETE; /* delete it */
290   dellist[0].fflags = 0;
291   dellist[0].data = 0;
292   dellist[0].udata = 0;
293
294   dellist[1].ident = s_fd(sock);
295   dellist[1].filter = EVFILT_WRITE; /* writable filter */
296   dellist[1].flags = EV_DELETE; /* delete it */
297   dellist[1].fflags = 0;
298   dellist[1].data = 0;
299   dellist[1].udata = 0;
300
301   sockList[s_fd(sock)] = 0;
302 }
303
304 /** Run engine event loop.
305  * @param[in] gen Lists of generators of various types.
306  */
307 static void
308 engine_loop(struct Generators* gen)
309 {
310   struct kevent *events;
311   int events_count;
312   struct Socket* sock;
313   struct timespec wait;
314   int nevs;
315   int i;
316   int errcode;
317   size_t codesize;
318
319   if ((events_count = feature_int(FEAT_POLLS_PER_LOOP)) < 20)
320     events_count = 20;
321   events = (struct kevent *)MyMalloc(sizeof(struct kevent) * events_count);
322
323   while (running) {
324     if ((i = feature_int(FEAT_POLLS_PER_LOOP)) >= 20 && i != events_count) {
325       events = (struct kevent *)MyRealloc(events, sizeof(struct kevent) * i);
326       events_count = i;
327     }
328
329     /* set up the sleep time */
330     wait.tv_sec = timer_next(gen) ? (timer_next(gen) - CurrentTime) : -1;
331     wait.tv_nsec = 0;
332
333     Debug((DEBUG_INFO, "kqueue: delay: %Tu (%Tu) %Tu", timer_next(gen),
334            CurrentTime, wait.tv_sec));
335
336     /* check for active events */
337     nevs = kevent(kqueue_id, 0, 0, events, events_count,
338                   wait.tv_sec < 0 ? 0 : &wait);
339
340     CurrentTime = time(0); /* set current time... */
341
342     if (nevs < 0) {
343       if (errno != EINTR) { /* ignore kevent interrupts */
344         /* Log the kqueue error */
345         log_write(LS_SOCKET, L_ERROR, 0, "kevent() error: %m");
346         if (!errors++)
347           timer_add(timer_init(&clear_error), error_clear, 0, TT_PERIODIC,
348                     ERROR_EXPIRE_TIME);
349         else if (errors > KQUEUE_ERROR_THRESHOLD) /* too many errors... */
350           server_restart("too many kevent errors");
351       }
352       /* old code did a sleep(1) here; with usage these days,
353        * that may be too expensive
354        */
355       continue;
356     }
357
358     for (i = 0; i < nevs; i++) {
359       if (events[i].filter == EVFILT_SIGNAL) {
360         /* it's a signal; deal appropriately */
361         event_generate(ET_SIGNAL, events[i].udata, events[i].ident);
362         continue; /* skip socket processing loop */
363       }
364
365       assert(events[i].filter == EVFILT_READ ||
366              events[i].filter == EVFILT_WRITE);
367
368       sock = sockList[events[i].ident];
369       if (!sock) /* slots may become empty while processing events */
370         continue;
371
372       assert(s_fd(sock) == events[i].ident);
373
374       gen_ref_inc(sock); /* can't have it going away on us */
375
376       Debug((DEBUG_ENGINE, "kqueue: Checking socket %p (fd %d) state %s, "
377              "events %s", sock, s_fd(sock), state_to_name(s_state(sock)),
378              sock_flags(s_events(sock))));
379
380       if (s_state(sock) != SS_NOTSOCK) {
381         errcode = 0; /* check for errors on socket */
382         codesize = sizeof(errcode);
383         if (getsockopt(s_fd(sock), SOL_SOCKET, SO_ERROR, &errcode,
384                        &codesize) < 0)
385           errcode = errno; /* work around Solaris implementation */
386
387         if (errcode) { /* an error occurred; generate an event */
388           Debug((DEBUG_ENGINE, "kqueue: Error %d on fd %d, socket %p", errcode,
389                  s_fd(sock), sock));
390           event_generate(ET_ERROR, sock, errcode);
391           gen_ref_dec(sock); /* careful not to leak reference counts */
392           continue;
393         }
394       }
395
396       switch (s_state(sock)) {
397       case SS_CONNECTING:
398         if (events[i].filter == EVFILT_WRITE) { /* connection completed */
399           Debug((DEBUG_ENGINE, "kqueue: Connection completed"));
400           event_generate(ET_CONNECT, sock, 0);
401         }
402         break;
403
404       case SS_LISTENING:
405         if (events[i].filter == EVFILT_READ) { /* connect. to be accept. */
406           Debug((DEBUG_ENGINE, "kqueue: Ready for accept"));
407           event_generate(ET_ACCEPT, sock, 0);
408         }
409         break;
410
411       case SS_NOTSOCK: /* doing nothing socket-specific */
412       case SS_CONNECTED:
413         if (events[i].filter == EVFILT_READ) { /* data on socket */
414           Debug((DEBUG_ENGINE, "kqueue: EOF or data to be read"));
415           event_generate(events[i].flags & EV_EOF ? ET_EOF : ET_READ, sock, 0);
416         }
417         if (events[i].filter == EVFILT_WRITE) { /* socket writable */
418           Debug((DEBUG_ENGINE, "kqueue: Data can be written"));
419           event_generate(ET_WRITE, sock, 0);
420         }
421         break;
422
423       case SS_DATAGRAM: case SS_CONNECTDG:
424         if (events[i].filter == EVFILT_READ) { /* socket readable */
425           Debug((DEBUG_ENGINE, "kqueue: Datagram to be read"));
426           event_generate(ET_READ, sock, 0);
427         }
428         if (events[i].filter == EVFILT_WRITE) { /* socket writable */
429           Debug((DEBUG_ENGINE, "kqueue: Datagram can be written"));
430           event_generate(ET_WRITE, sock, 0);
431         }
432         break;
433       }
434
435       gen_ref_dec(sock); /* we're done with it */
436     }
437
438     timer_run(); /* execute any pending timers */
439   }
440 }
441
442 /** Descriptor for kqueue() event engine. */
443 struct Engine engine_kqueue = {
444   "kqueue()",           /* Engine name */
445   engine_init,          /* Engine initialization function */
446   engine_signal,        /* Engine signal registration function */
447   engine_add,           /* Engine socket registration function */
448   engine_state,         /* Engine socket state change function */
449   engine_events,        /* Engine socket events mask function */
450   engine_delete,        /* Engine socket deletion function */
451   engine_loop           /* Core engine event loop */
452 };