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