1 /* $OpenBSD: accept.c,v 1.1 2012/11/13 17:10:40 yasuoka Exp $ */
2
3 /*
4 * Copyright (c) 2012 Claudio Jeker <claudio@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/queue.h>
20 #include <sys/time.h>
21 #include <event.h>
22 #include <stdlib.h>
23
24 #include "accept.h"
25 #include "log.h"
26
27
28 struct accept_ev {
29 LIST_ENTRY(accept_ev) entry;
30 struct event ev;
31 void (*accept_cb)(int, short, void *);
32 void *arg;
33 int fd;
34 };
35
36 struct {
37 LIST_HEAD(, accept_ev) queue;
38 struct event evt;
39 } accept_queue;
40
41 void accept_arm(void);
42 void accept_unarm(void);
43 void accept_cb(int, short, void *);
44 void accept_timeout(int, short, void *);
45
46 void
accept_init(void)47 accept_init(void)
48 {
49 LIST_INIT(&accept_queue.queue);
50 evtimer_set(&accept_queue.evt, accept_timeout, NULL);
51 }
52
53 int
accept_add(int fd,void (* cb)(int,short,void *),void * arg)54 accept_add(int fd, void (*cb)(int, short, void *), void *arg)
55 {
56 struct accept_ev *av;
57
58 if ((av = calloc(1, sizeof(*av))) == NULL)
59 return -1;
60 av->fd = fd;
61 av->accept_cb = cb;
62 av->arg = arg;
63 LIST_INSERT_HEAD(&accept_queue.queue, av, entry);
64
65 event_set(&av->ev, av->fd, EV_READ, accept_cb, av);
66 event_add(&av->ev, NULL);
67
68 log_debug("accept_add: accepting on fd %d", fd);
69
70 return (0);
71 }
72
73 void
accept_del(int fd)74 accept_del(int fd)
75 {
76 struct accept_ev *av;
77
78 LIST_FOREACH(av, &accept_queue.queue, entry)
79 if (av->fd == fd) {
80 log_debug("accept_del: %i removed from queue", fd);
81 event_del(&av->ev);
82 LIST_REMOVE(av, entry);
83 free(av);
84 return;
85 }
86 }
87
88 void
accept_pause(void)89 accept_pause(void)
90 {
91 struct timeval evtpause = { 1, 0 };
92
93 log_debug("accept_pause");
94 accept_unarm();
95 evtimer_add(&accept_queue.evt, &evtpause);
96 }
97
98 void
accept_unpause(void)99 accept_unpause(void)
100 {
101 if (evtimer_pending(&accept_queue.evt, NULL)) {
102 log_debug("accept_unpause");
103 evtimer_del(&accept_queue.evt);
104 accept_arm();
105 }
106 }
107
108 void
accept_arm(void)109 accept_arm(void)
110 {
111 struct accept_ev *av;
112 LIST_FOREACH(av, &accept_queue.queue, entry)
113 event_add(&av->ev, NULL);
114 }
115
116 void
accept_unarm(void)117 accept_unarm(void)
118 {
119 struct accept_ev *av;
120 LIST_FOREACH(av, &accept_queue.queue, entry)
121 event_del(&av->ev);
122 }
123
124 void
accept_cb(int fd,short event,void * arg)125 accept_cb(int fd, short event, void *arg)
126 {
127 struct accept_ev *av = arg;
128 event_add(&av->ev, NULL);
129 av->accept_cb(fd, event, av->arg);
130 }
131
132 void
accept_timeout(int fd,short event,void * bula)133 accept_timeout(int fd, short event, void *bula)
134 {
135 log_debug("accept_timeout");
136 accept_arm();
137 }
138