]> jfr.im git - irc/rqf/shadowircd.git/blame - libratbox/src/devpoll.c
Copied libratbox and related stuff from shadowircd upstream.
[irc/rqf/shadowircd.git] / libratbox / src / devpoll.c
CommitLineData
b57f37fb
WP
1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * s_bsd_devpoll.c: /dev/poll compatible network routines.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2001 Adrian Chadd <adrian@creative.net.au>
8 * Copyright (C) 2002-2005 ircd-ratbox development team
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
23 * USA
24 *
94b4fbf9 25 * $Id: devpoll.c 26092 2008-09-19 15:13:52Z androsyn $
b57f37fb
WP
26 */
27#include <libratbox_config.h>
28#include <ratbox_lib.h>
29#include <commio-int.h>
30#include <fcntl.h>
31
32#if defined(HAVE_DEVPOLL) && (HAVE_DEVPOLL_H)
33#include <sys/devpoll.h>
34
35
36static void devpoll_update_events(int, short, PF *);
37static int dpfd;
38static int maxfd;
39static short *fdmask;
40static void devpoll_update_events(int, short, PF *);
41static void devpoll_write_update(int, int);
42
43
94b4fbf9 44int
b57f37fb
WP
45rb_setup_fd_devpoll(rb_fde_t *F)
46{
94b4fbf9 47 return 0;
b57f37fb 48}
94b4fbf9
VY
49
50
b57f37fb
WP
51/*
52 * Write an update to the devpoll filter.
53 * See, we end up having to do a seperate (?) remove before we do an
54 * add of a new polltype, so we have to have this function seperate from
55 * the others.
56 */
57static void
58devpoll_write_update(int fd, int events)
59{
60 struct pollfd pollfds[1]; /* Just to be careful */
61 int retval;
62
63 /* Build the pollfd entry */
64 pollfds[0].revents = 0;
65 pollfds[0].fd = fd;
66 pollfds[0].events = events;
67
68 /* Write the thing to our poll fd */
69 retval = write(dpfd, &pollfds[0], sizeof(struct pollfd));
70 if(retval != sizeof(struct pollfd))
94b4fbf9
VY
71 rb_lib_log("devpoll_write_update: dpfd write failed %d: %s", errno,
72 strerror(errno));
b57f37fb
WP
73 /* Done! */
74}
75
76static void
77devpoll_update_events(int fd, short filter, PF * handler)
78{
79 int update_required = 0;
80 int cur_mask = fdmask[fd];
81 PF *cur_handler;
82
83 fdmask[fd] = 0;
84 switch (filter)
85 {
86 case RB_SELECT_READ:
87 cur_handler = F->read_handler;
88 if(handler)
89 fdmask[fd] |= POLLRDNORM;
90 else
91 fdmask[fd] &= ~POLLRDNORM;
92 if(F->write_handler)
93 fdmask[fd] |= POLLWRNORM;
94 break;
95 case RB_SELECT_WRITE:
96 cur_handler = F->write_handler;
97 if(handler)
98 fdmask[fd] |= POLLWRNORM;
99 else
100 fdmask[fd] &= ~POLLWRNORM;
101 if(F->read_handler)
102 fdmask[fd] |= POLLRDNORM;
103 break;
104 default:
105 return;
106 break;
107 }
108
109 if(cur_handler == NULL && handler != NULL)
110 update_required++;
111 else if(cur_handler != NULL && handler == NULL)
112 update_required++;
113 if(cur_mask != fdmask[fd])
114 update_required++;
115 if(update_required)
116 {
117 /*
118 * Ok, we can call devpoll_write_update() here now to re-build the
119 * fd struct. If we end up with nothing on this fd, it won't write
120 * anything.
121 */
122 if(fdmask[fd])
123 {
124 devpoll_write_update(fd, POLLREMOVE);
125 devpoll_write_update(fd, fdmask[fd]);
126 }
127 else
128 devpoll_write_update(fd, POLLREMOVE);
129 }
130}
131
132
133
134
135
136/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
137/* Public functions */
138
139
140/*
141 * rb_init_netio
142 *
143 * This is a needed exported function which will be called to initialise
144 * the network loop code.
145 */
146int
147rb_init_netio_devpoll(void)
148{
149 dpfd = open("/dev/poll", O_RDWR);
150 if(dpfd < 0)
151 {
152 return errno;
153 }
94b4fbf9 154 maxfd = getdtablesize() - 2; /* This makes more sense than HARD_FDLIMIT */
b57f37fb
WP
155 fdmask = rb_malloc(sizeof(fdmask) * maxfd + 1);
156 rb_open(dpfd, RB_FD_UNKNOWN, "/dev/poll file descriptor");
157}
158
159/*
160 * rb_setselect
161 *
162 * This is a needed exported function which will be called to register
163 * and deregister interest in a pending IO state for a given FD.
164 */
165void
94b4fbf9 166rb_setselect_devpoll(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
b57f37fb
WP
167{
168 lrb_assert(IsFDOpen(F));
169
170 if(type & RB_SELECT_READ)
171 {
172 devpoll_update_events(fd, RB_SELECT_READ, handler);
173 F->read_handler = handler;
174 F->read_data = client_data;
175 }
176 if(type & RB_SELECT_WRITE)
177 {
178 devpoll_update_events(fd, RB_SELECT_WRITE, handler);
179 F->write_handler = handler;
180 F->write_data = client_data;
181 }
182}
183
184/*
185 * Check all connections for new connections and input data that is to be
186 * processed. Also check for connections with data queued and whether we can
187 * write it out.
188 */
189
190/*
191 * rb_select
192 *
193 * Called to do the new-style IO, courtesy of squid (like most of this
194 * new IO code). This routine handles the stuff we've hidden in
195 * rb_setselect and fd_table[] and calls callbacks for IO ready
196 * events.
197 */
198
199int
200rb_select_devpoll(long delay)
201{
202 int num, i;
203 struct pollfd pollfds[maxfd];
204 struct dvpoll dopoll;
205
206 do
207 {
94b4fbf9 208 for(;;)
b57f37fb
WP
209 {
210 dopoll.dp_timeout = delay;
211 dopoll.dp_nfds = maxfd;
212 dopoll.dp_fds = &pollfds[0];
213 num = ioctl(dpfd, DP_POLL, &dopoll);
214 if(num >= 0)
215 break;
216 if(rb_ignore_errno(errno))
217 break;
218 rb_set_time();
219 return RB_ERROR;
220 }
221
222 rb_set_time();
223 if(num == 0)
224 continue;
225
94b4fbf9 226 for(i = 0; i < num; i++)
b57f37fb
WP
227 {
228 int fd = dopoll.dp_fds[i].fd;
229 PF *hdl = NULL;
230 rb_fde_t *F = rb_find_fd(fd);
94b4fbf9
VY
231 if((dopoll.dp_fds[i].revents & (POLLRDNORM | POLLIN | POLLHUP |
232 POLLERR))
b57f37fb
WP
233 && (dopoll.dp_fds[i].events & (POLLRDNORM | POLLIN)))
234 {
235 if((hdl = F->read_handler) != NULL)
236 {
237 F->read_handler = NULL;
238 hdl(F, F->read_data);
239 /*
240 * this call used to be with a NULL pointer, BUT
241 * in the devpoll case we only want to update the
242 * poll set *if* the handler changes state (active ->
243 * NULL or vice versa.)
244 */
94b4fbf9 245 devpoll_update_events(fd, RB_SELECT_READ, F->read_handler);
b57f37fb
WP
246 }
247 }
248
249 if(!IsFDOpen(F))
250 continue; /* Read handler closed us..go on to do something more useful */
94b4fbf9
VY
251 if((dopoll.dp_fds[i].revents & (POLLWRNORM | POLLOUT | POLLHUP |
252 POLLERR))
b57f37fb
WP
253 && (dopoll.dp_fds[i].events & (POLLWRNORM | POLLOUT)))
254 {
255 if((hdl = F->write_handler) != NULL)
256 {
257 F->write_handler = NULL;
258 hdl(F, F->write_data);
259 /* See above similar code in the read case */
260 devpoll_update_events(fd,
261 RB_SELECT_WRITE, F->write_handler);
262 }
263
264 }
265 }
266 return RB_OK;
267 }
94b4fbf9 268 while(0);
b57f37fb
WP
269 /* XXX Get here, we broke! */
270 return 0;
271}
272
273#else /* /dev/poll not supported */
94b4fbf9 274int
b57f37fb
WP
275rb_init_netio_devpoll(void)
276{
277 return ENOSYS;
278}
279
280void
281rb_setselect_devpoll(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
282{
283 errno = ENOSYS;
284 return;
285}
286
287int
288rb_select_devpoll(long delay)
289{
290 errno = ENOSYS;
291 return -1;
292}
293
294int
295rb_setup_fd_devpoll(rb_fde_t *F)
296{
297 errno = ENOSYS;
298 return -1;
299}
300#endif