xref: /openbsd-src/usr.sbin/ldpd/accept.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$OpenBSD: accept.c,v 1.3 2013/10/31 16:56:22 deraadt 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 "ldpd.h"
25 #include "ldpe.h"
26 #include "log.h"
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
47 accept_init(void)
48 {
49 	LIST_INIT(&accept_queue.queue);
50 	evtimer_set(&accept_queue.evt, accept_timeout, NULL);
51 }
52 
53 int
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
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: %d removed from queue", fd);
81 			event_del(&av->ev);
82 			LIST_REMOVE(av, entry);
83 			free(av);
84 			return;
85 		}
86 }
87 
88 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
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
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
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
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
133 accept_timeout(int fd, short event, void *bula)
134 {
135 	log_debug("accept_timeout");
136 	accept_arm();
137 }
138