Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / rp-l2tp / libevent / event.c
blob398ac39223419baaa3f905993004943851a21e24
1 /***********************************************************************
3 * event.c
5 * Abstraction of select call into "event-handling" to make programming
6 * easier.
8 * Copyright (C) 2001 Roaring Penguin Software Inc.
10 * This program may be distributed according to the terms of the GNU
11 * General Public License, version 2 or (at your option) any later version.
13 * LIC: GPL
15 ***********************************************************************/
17 static char const RCSID[] =
18 "$Id: event.c,v 1.1.48.1 2005/08/08 12:05:25 honor Exp $";
20 #include "event.h"
21 #include <stdlib.h>
22 #include <errno.h>
24 static void DestroySelector(EventSelector *es);
25 static void DestroyHandler(EventHandler *eh);
26 static void DoPendingChanges(EventSelector *es);
28 /**********************************************************************
29 * %FUNCTION: Event_CreateSelector
30 * %ARGUMENTS:
31 * None
32 * %RETURNS:
33 * A newly-allocated EventSelector, or NULL if out of memory.
34 * %DESCRIPTION:
35 * Creates a new EventSelector.
36 ***********************************************************************/
37 EventSelector *
38 Event_CreateSelector(void)
40 EventSelector *es = malloc(sizeof(EventSelector));
41 if (!es) return NULL;
42 es->handlers = NULL;
43 es->nestLevel = 0;
44 es->destroyPending = 0;
45 es->opsPending = 0;
46 EVENT_DEBUG(("CreateSelector() -> %p\n", (void *) es));
47 return es;
50 /**********************************************************************
51 * %FUNCTION: Event_DestroySelector
52 * %ARGUMENTS:
53 * es -- EventSelector to destroy
54 * %RETURNS:
55 * Nothing
56 * %DESCRIPTION:
57 * Destroys an EventSelector. Destruction may be delayed if we
58 * are in the HandleEvent function.
59 ***********************************************************************/
60 void
61 Event_DestroySelector(EventSelector *es)
63 if (es->nestLevel) {
64 es->destroyPending = 1;
65 es->opsPending = 1;
66 return;
68 DestroySelector(es);
71 /**********************************************************************
72 * %FUNCTION: Event_HandleEvent
73 * %ARGUMENTS:
74 * es -- EventSelector
75 * %RETURNS:
76 * 0 if OK, non-zero on error. errno is set appropriately.
77 * %DESCRIPTION:
78 * Handles a single event (uses select() to wait for an event.)
79 ***********************************************************************/
80 int
81 Event_HandleEvent(EventSelector *es)
83 fd_set readfds, writefds;
84 fd_set *rd, *wr;
85 unsigned int flags;
87 struct timeval abs_timeout, now;
88 struct timeval timeout;
89 struct timeval *tm;
90 EventHandler *eh;
92 int r = 0;
93 int errno_save = 0;
94 int foundTimeoutEvent = 0;
95 int foundReadEvent = 0;
96 int foundWriteEvent = 0;
97 int maxfd = -1;
98 int pastDue;
100 EVENT_DEBUG(("Enter Event_HandleEvent(es=%p)\n", (void *) es));
102 /* Build the select sets */
103 FD_ZERO(&readfds);
104 FD_ZERO(&writefds);
106 eh = es->handlers;
107 for (eh=es->handlers; eh; eh=eh->next) {
108 if (eh->flags & EVENT_FLAG_DELETED) continue;
109 if (eh->flags & EVENT_FLAG_READABLE) {
110 foundReadEvent = 1;
111 FD_SET(eh->fd, &readfds);
112 if (eh->fd > maxfd) maxfd = eh->fd;
114 if (eh->flags & EVENT_FLAG_WRITEABLE) {
115 foundWriteEvent = 1;
116 FD_SET(eh->fd, &writefds);
117 if (eh->fd > maxfd) maxfd = eh->fd;
119 if (eh->flags & EVENT_TIMER_BITS) {
120 if (!foundTimeoutEvent) {
121 abs_timeout = eh->tmout;
122 foundTimeoutEvent = 1;
123 } else {
124 if (eh->tmout.tv_sec < abs_timeout.tv_sec ||
125 (eh->tmout.tv_sec == abs_timeout.tv_sec &&
126 eh->tmout.tv_usec < abs_timeout.tv_usec)) {
127 abs_timeout = eh->tmout;
132 if (foundReadEvent) {
133 rd = &readfds;
134 } else {
135 rd = NULL;
137 if (foundWriteEvent) {
138 wr = &writefds;
139 } else {
140 wr = NULL;
143 if (foundTimeoutEvent) {
144 gettimeofday(&now, NULL);
145 /* Convert absolute timeout to relative timeout for select */
146 timeout.tv_usec = abs_timeout.tv_usec - now.tv_usec;
147 timeout.tv_sec = abs_timeout.tv_sec - now.tv_sec;
148 if (timeout.tv_usec < 0) {
149 timeout.tv_usec += 1000000;
150 timeout.tv_sec--;
152 if (timeout.tv_sec < 0 ||
153 (timeout.tv_sec == 0 && timeout.tv_usec < 0)) {
154 timeout.tv_sec = 0;
155 timeout.tv_usec = 0;
157 tm = &timeout;
158 } else {
159 tm = NULL;
162 if (foundReadEvent || foundWriteEvent || foundTimeoutEvent) {
163 for(;;) {
164 r = select(maxfd+1, rd, wr, NULL, tm);
165 if (r < 0) {
166 if (errno == EINTR) continue;
168 break;
172 if (foundTimeoutEvent) gettimeofday(&now, NULL);
173 errno_save = errno;
174 es->nestLevel++;
176 if (r >= 0) {
177 /* Call handlers */
178 for (eh=es->handlers; eh; eh=eh->next) {
180 /* Pending delete for this handler? Ignore it */
181 if (eh->flags & EVENT_FLAG_DELETED) continue;
183 flags = 0;
184 if ((eh->flags & EVENT_FLAG_READABLE) &&
185 FD_ISSET(eh->fd, &readfds)) {
186 flags |= EVENT_FLAG_READABLE;
188 if ((eh->flags & EVENT_FLAG_WRITEABLE) &&
189 FD_ISSET(eh->fd, &writefds)) {
190 flags |= EVENT_FLAG_WRITEABLE;
192 if (eh->flags & EVENT_TIMER_BITS) {
193 pastDue = (eh->tmout.tv_sec < now.tv_sec ||
194 (eh->tmout.tv_sec == now.tv_sec &&
195 eh->tmout.tv_usec <= now.tv_usec));
196 if (pastDue) {
197 flags |= EVENT_TIMER_BITS;
198 if (eh->flags & EVENT_FLAG_TIMER) {
199 /* Timer events are only called once */
200 es->opsPending = 1;
201 eh->flags |= EVENT_FLAG_DELETED;
205 /* Do callback */
206 if (flags) {
207 EVENT_DEBUG(("Enter callback: eh=%p flags=%u\n", eh, flags));
208 eh->fn(es, eh->fd, flags, eh->data);
209 EVENT_DEBUG(("Leave callback: eh=%p flags=%u\n", eh, flags));
214 es->nestLevel--;
216 if (!es->nestLevel && es->opsPending) {
217 DoPendingChanges(es);
219 errno = errno_save;
220 return r;
223 /**********************************************************************
224 * %FUNCTION: Event_AddHandler
225 * %ARGUMENTS:
226 * es -- event selector
227 * fd -- file descriptor to watch
228 * flags -- combination of EVENT_FLAG_READABLE and EVENT_FLAG_WRITEABLE
229 * fn -- callback function to call when event is triggered
230 * data -- extra data to pass to callback function
231 * %RETURNS:
232 * A newly-allocated EventHandler, or NULL.
233 ***********************************************************************/
234 EventHandler *
235 Event_AddHandler(EventSelector *es,
236 int fd,
237 unsigned int flags,
238 EventCallbackFunc fn,
239 void *data)
241 EventHandler *eh;
243 /* Specifically disable timer and deleted flags */
244 flags &= (~(EVENT_TIMER_BITS | EVENT_FLAG_DELETED));
246 /* Bad file descriptor */
247 if (fd < 0) {
248 errno = EBADF;
249 return NULL;
252 eh = malloc(sizeof(EventHandler));
253 if (!eh) return NULL;
254 eh->fd = fd;
255 eh->flags = flags;
256 eh->tmout.tv_usec = 0;
257 eh->tmout.tv_sec = 0;
258 eh->fn = fn;
259 eh->data = data;
261 /* Add immediately. This is safe even if we are in a handler. */
262 eh->next = es->handlers;
263 es->handlers = eh;
265 EVENT_DEBUG(("Event_AddHandler(es=%p, fd=%d, flags=%u) -> %p\n", es, fd, flags, eh));
266 return eh;
269 /**********************************************************************
270 * %FUNCTION: Event_AddHandlerWithTimeout
271 * %ARGUMENTS:
272 * es -- event selector
273 * fd -- file descriptor to watch
274 * flags -- combination of EVENT_FLAG_READABLE and EVENT_FLAG_WRITEABLE
275 * t -- Timeout after which to call handler, even if not readable/writable.
276 * If t.tv_sec < 0, calls normal Event_AddHandler with no timeout.
277 * fn -- callback function to call when event is triggered
278 * data -- extra data to pass to callback function
279 * %RETURNS:
280 * A newly-allocated EventHandler, or NULL.
281 ***********************************************************************/
282 EventHandler *
283 Event_AddHandlerWithTimeout(EventSelector *es,
284 int fd,
285 unsigned int flags,
286 struct timeval t,
287 EventCallbackFunc fn,
288 void *data)
290 EventHandler *eh;
291 struct timeval now;
293 /* If timeout is negative, just do normal non-timing-out event */
294 if (t.tv_sec < 0 || t.tv_usec < 0) {
295 return Event_AddHandler(es, fd, flags, fn, data);
298 /* Specifically disable timer and deleted flags */
299 flags &= (~(EVENT_FLAG_TIMER | EVENT_FLAG_DELETED));
300 flags |= EVENT_FLAG_TIMEOUT;
302 /* Bad file descriptor? */
303 if (fd < 0) {
304 errno = EBADF;
305 return NULL;
308 /* Bad timeout? */
309 if (t.tv_usec >= 1000000) {
310 errno = EINVAL;
311 return NULL;
314 eh = malloc(sizeof(EventHandler));
315 if (!eh) return NULL;
317 /* Convert time interval to absolute time */
318 gettimeofday(&now, NULL);
320 t.tv_sec += now.tv_sec;
321 t.tv_usec += now.tv_usec;
322 if (t.tv_usec >= 1000000) {
323 t.tv_usec -= 1000000;
324 t.tv_sec++;
327 eh->fd = fd;
328 eh->flags = flags;
329 eh->tmout = t;
330 eh->fn = fn;
331 eh->data = data;
333 /* Add immediately. This is safe even if we are in a handler. */
334 eh->next = es->handlers;
335 es->handlers = eh;
337 EVENT_DEBUG(("Event_AddHandlerWithTimeout(es=%p, fd=%d, flags=%u, t=%d/%d) -> %p\n", es, fd, flags, t.tv_sec, t.tv_usec, eh));
338 return eh;
342 /**********************************************************************
343 * %FUNCTION: Event_AddTimerHandler
344 * %ARGUMENTS:
345 * es -- event selector
346 * t -- time interval after which to trigger event
347 * fn -- callback function to call when event is triggered
348 * data -- extra data to pass to callback function
349 * %RETURNS:
350 * A newly-allocated EventHandler, or NULL.
351 ***********************************************************************/
352 EventHandler *
353 Event_AddTimerHandler(EventSelector *es,
354 struct timeval t,
355 EventCallbackFunc fn,
356 void *data)
358 EventHandler *eh;
359 struct timeval now;
361 /* Check time interval for validity */
362 if (t.tv_sec < 0 || t.tv_usec < 0 || t.tv_usec >= 1000000) {
363 errno = EINVAL;
364 return NULL;
367 eh = malloc(sizeof(EventHandler));
368 if (!eh) return NULL;
370 /* Convert time interval to absolute time */
371 gettimeofday(&now, NULL);
373 t.tv_sec += now.tv_sec;
374 t.tv_usec += now.tv_usec;
375 if (t.tv_usec >= 1000000) {
376 t.tv_usec -= 1000000;
377 t.tv_sec++;
380 eh->fd = -1;
381 eh->flags = EVENT_FLAG_TIMER;
382 eh->tmout = t;
383 eh->fn = fn;
384 eh->data = data;
386 /* Add immediately. This is safe even if we are in a handler. */
387 eh->next = es->handlers;
388 es->handlers = eh;
390 EVENT_DEBUG(("Event_AddTimerHandler(es=%p, t=%d/%d) -> %p\n", es, t.tv_sec,t.tv_usec, eh));
391 return eh;
394 /**********************************************************************
395 * %FUNCTION: Event_DelHandler
396 * %ARGUMENTS:
397 * es -- event selector
398 * eh -- event handler
399 * %RETURNS:
400 * 0 if OK, non-zero if there is an error
401 * %DESCRIPTION:
402 * Deletes the event handler eh
403 ***********************************************************************/
405 Event_DelHandler(EventSelector *es,
406 EventHandler *eh)
408 /* Scan the handlers list */
409 EventHandler *cur, *prev;
410 EVENT_DEBUG(("Event_DelHandler(es=%p, eh=%p)\n", es, eh));
411 for (cur=es->handlers, prev=NULL; cur; prev=cur, cur=cur->next) {
412 if (cur == eh) {
413 if (es->nestLevel) {
414 eh->flags |= EVENT_FLAG_DELETED;
415 es->opsPending = 1;
416 return 0;
417 } else {
418 if (prev) prev->next = cur->next;
419 else es->handlers = cur->next;
421 DestroyHandler(cur);
422 return 0;
427 /* Handler not found */
428 return 1;
431 /**********************************************************************
432 * %FUNCTION: DestroySelector
433 * %ARGUMENTS:
434 * es -- an event selector
435 * %RETURNS:
436 * Nothing
437 * %DESCRIPTION:
438 * Destroys selector and all associated handles.
439 ***********************************************************************/
440 void
441 DestroySelector(EventSelector *es)
443 EventHandler *cur, *next;
444 for (cur=es->handlers; cur; cur=next) {
445 next = cur->next;
446 DestroyHandler(cur);
449 free(es);
452 /**********************************************************************
453 * %FUNCTION: DestroyHandler
454 * %ARGUMENTS:
455 * eh -- an event handler
456 * %RETURNS:
457 * Nothing
458 * %DESCRIPTION:
459 * Destroys handler
460 ***********************************************************************/
461 void
462 DestroyHandler(EventHandler *eh)
464 EVENT_DEBUG(("DestroyHandler(eh=%p)\n", eh));
465 free(eh);
468 /**********************************************************************
469 * %FUNCTION: DoPendingChanges
470 * %ARGUMENTS:
471 * es -- an event selector
472 * %RETURNS:
473 * Nothing
474 * %DESCRIPTION:
475 * Makes all pending insertions and deletions happen.
476 ***********************************************************************/
477 void
478 DoPendingChanges(EventSelector *es)
480 EventHandler *cur, *prev, *next;
482 es->opsPending = 0;
484 /* If selector is to be deleted, do it and skip everything else */
485 if (es->destroyPending) {
486 DestroySelector(es);
487 return;
490 /* Do deletions */
491 cur = es->handlers;
492 prev = NULL;
493 while(cur) {
494 if (!(cur->flags & EVENT_FLAG_DELETED)) {
495 prev = cur;
496 cur = cur->next;
497 continue;
500 /* Unlink from list */
501 if (prev) {
502 prev->next = cur->next;
503 } else {
504 es->handlers = cur->next;
506 next = cur->next;
507 DestroyHandler(cur);
508 cur = next;
512 /**********************************************************************
513 * %FUNCTION: Event_GetCallback
514 * %ARGUMENTS:
515 * eh -- the event handler
516 * %RETURNS:
517 * The callback function
518 ***********************************************************************/
519 EventCallbackFunc
520 Event_GetCallback(EventHandler *eh)
522 return eh->fn;
525 /**********************************************************************
526 * %FUNCTION: Event_GetData
527 * %ARGUMENTS:
528 * eh -- the event handler
529 * %RETURNS:
530 * The "data" field.
531 ***********************************************************************/
532 void *
533 Event_GetData(EventHandler *eh)
535 return eh->data;
538 /**********************************************************************
539 * %FUNCTION: Event_SetCallbackAndData
540 * %ARGUMENTS:
541 * eh -- the event handler
542 * fn -- new callback function
543 * data -- new data value
544 * %RETURNS:
545 * Nothing
546 * %DESCRIPTION:
547 * Sets the callback function and data fields.
548 ***********************************************************************/
549 void
550 Event_SetCallbackAndData(EventHandler *eh,
551 EventCallbackFunc fn,
552 void *data)
554 eh->fn = fn;
555 eh->data = data;
558 #ifdef DEBUG_EVENT
559 #include <stdarg.h>
560 #include <stdio.h>
561 FILE *Event_DebugFP = NULL;
562 /**********************************************************************
563 * %FUNCTION: Event_DebugMsg
564 * %ARGUMENTS:
565 * fmt, ... -- format string
566 * %RETURNS:
567 * Nothing
568 * %DESCRIPTION:
569 * Writes a debug message to the debug file.
570 ***********************************************************************/
571 void
572 Event_DebugMsg(char const *fmt, ...)
574 va_list ap;
575 struct timeval now;
577 if (!Event_DebugFP) return;
579 gettimeofday(&now, NULL);
581 fprintf(Event_DebugFP, "%03d.%03d ", (int) now.tv_sec % 1000,
582 (int) now.tv_usec / 1000);
584 va_start(ap, fmt);
585 vfprintf(Event_DebugFP, fmt, ap);
586 va_end(ap);
587 fflush(Event_DebugFP);
590 #endif
592 /**********************************************************************
593 * %FUNCTION: Event_EnableDebugging
594 * %ARGUMENTS:
595 * fname -- name of file to log debug messages to
596 * %RETURNS:
597 * 1 if debugging was enabled; 0 otherwise.
598 ***********************************************************************/
600 Event_EnableDebugging(char const *fname)
602 #ifndef DEBUG_EVENT
603 return 0;
604 #else
605 Event_DebugFP = fopen(fname, "w");
606 return (Event_DebugFP != NULL);
607 #endif
610 /**********************************************************************
611 * %FUNCTION: Event_ChangeTimeout
612 * %ARGUMENTS:
613 * h -- event handler
614 * t -- new timeout
615 * %RETURNS:
616 * Nothing
617 * %DESCRIPTION:
618 * Changes timeout of event handler to be "t" seconds in the future.
619 ***********************************************************************/
620 void
621 Event_ChangeTimeout(EventHandler *h, struct timeval t)
623 struct timeval now;
625 /* Check time interval for validity */
626 if (t.tv_sec < 0 || t.tv_usec < 0 || t.tv_usec >= 1000000) {
627 return;
629 /* Convert time interval to absolute time */
630 gettimeofday(&now, NULL);
632 t.tv_sec += now.tv_sec;
633 t.tv_usec += now.tv_usec;
634 if (t.tv_usec >= 1000000) {
635 t.tv_usec -= 1000000;
636 t.tv_sec++;
639 h->tmout = t;