Initial import
[ratbox-ambernet.git] / src / devpoll.c
blob710b43fa7fbf39b172d8c2c6f8920fe3e16d9e0c
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * s_bsd_devpoll.c: /dev/poll compatible network routines.
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
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 * USA
25 * $Id: devpoll.c 21876 2006-02-21 19:12:53Z androsyn $
28 #include "config.h"
30 #include "stdinc.h"
31 #include <poll.h>
32 #include <sys/devpoll.h>
34 #include "config.h"
35 #include "commio.h"
36 #include "class.h"
37 #include "client.h"
38 #include "common.h"
39 #include "irc_string.h"
40 #include "ircd.h"
41 #include "listener.h"
42 #include "numeric.h"
43 #include "packet.h"
44 #include "res.h"
45 #include "restart.h"
46 #include "s_auth.h"
47 #include "s_conf.h"
48 #include "s_log.h"
49 #include "s_serv.h"
50 #include "s_stats.h"
51 #include "send.h"
52 #include "commio.h"
53 #include "memory.h"
55 static void devpoll_update_events(int, short, PF *);
56 static int dpfd;
57 static short *fdmask;
58 static struct pollfd *npollfds;
59 static void devpoll_update_events(int, short, PF *);
60 static void devpoll_write_update(int, int);
61 static int maxfd;
63 /* #define NOTYET 1 */
65 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
66 /* Private functions */
68 int
69 comm_setup_fd(int fd)
71 return 0;
76 * Write an update to the devpoll filter.
77 * See, we end up having to do a seperate (?) remove before we do an
78 * add of a new polltype, so we have to have this function seperate from
79 * the others.
81 static void
82 devpoll_write_update(int fd, int events)
84 struct pollfd pollfds[1]; /* Just to be careful */
85 int retval;
87 /* Build the pollfd entry */
88 pollfds[0].revents = 0;
89 pollfds[0].fd = fd;
90 pollfds[0].events = events;
92 /* Write the thing to our poll fd */
93 retval = write(dpfd, &pollfds[0], sizeof(struct pollfd));
94 if(retval != sizeof(struct pollfd))
95 ilog(L_IOERROR,
96 "devpoll_write_update: dpfd write failed %d: %s", errno, strerror(errno));
97 /* Done! */
100 void
101 devpoll_update_events(int fd, short filter, PF * handler)
103 int update_required = 0;
104 int cur_mask = fdmask[fd];
105 PF *cur_handler;
106 fdmask[fd] = 0;
107 switch (filter)
109 case COMM_SELECT_READ:
110 cur_handler = fd_table[fd].read_handler;
111 if(handler)
112 fdmask[fd] |= POLLRDNORM;
113 else
114 fdmask[fd] &= ~POLLRDNORM;
115 if(fd_table[fd].write_handler)
116 fdmask[fd] |= POLLWRNORM;
117 break;
118 case COMM_SELECT_WRITE:
119 cur_handler = fd_table[fd].write_handler;
120 if(handler)
121 fdmask[fd] |= POLLWRNORM;
122 else
123 fdmask[fd] &= ~POLLWRNORM;
124 if(fd_table[fd].read_handler)
125 fdmask[fd] |= POLLRDNORM;
126 break;
127 default:
128 #ifdef NOTYET
129 ilog(L_IOERROR, "devpoll_update_events called with unknown filter: %hd", filter);
130 #endif
131 return;
132 break;
135 if(cur_handler == NULL && handler != NULL)
136 update_required++;
137 else if(cur_handler != NULL && handler == NULL)
138 update_required++;
139 if(cur_mask != fdmask[fd])
140 update_required++;
141 if(update_required)
144 * Ok, we can call devpoll_write_update() here now to re-build the
145 * fd struct. If we end up with nothing on this fd, it won't write
146 * anything.
148 if(fdmask[fd])
150 devpoll_write_update(fd, POLLREMOVE);
151 devpoll_write_update(fd, fdmask[fd]);
153 else
154 devpoll_write_update(fd, POLLREMOVE);
162 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
163 /* Public functions */
167 * init_netio
169 * This is a needed exported function which will be called to initialise
170 * the network loop code.
172 void
173 init_netio(void)
175 maxfd = getdtablesize() - 2; /* This makes more sense than HARD_FDLIMIT */
176 fdmask = MyMalloc(sizeof(fdmask) * maxfd + 1);
177 npollfds = MyMalloc(sizeof(struct pollfd) * maxfd + 1);
179 dpfd = open("/dev/poll", O_RDWR);
180 if(dpfd < 0)
182 fprintf(stderr,
183 "init_netio: Couldn't open /dev/poll - %d: %s\n",
184 errno, strerror(errno));
185 exit(115); /* Whee! */
190 * comm_setselect
192 * This is a needed exported function which will be called to register
193 * and deregister interest in a pending IO state for a given FD.
195 void
196 comm_setselect(int fd, fdlist_t list, unsigned int type, PF * handler,
197 void *client_data)
199 fde_t *F = &fd_table[fd];
200 s_assert(fd >= 0);
201 s_assert(F->flags.open);
203 /* Update the list, even though we're not using it .. */
204 F->list = list;
206 if(type & COMM_SELECT_READ)
208 devpoll_update_events(fd, COMM_SELECT_READ, handler);
209 F->read_handler = handler;
210 F->read_data = client_data;
212 if(type & COMM_SELECT_WRITE)
214 devpoll_update_events(fd, COMM_SELECT_WRITE, handler);
215 F->write_handler = handler;
216 F->write_data = client_data;
221 * Check all connections for new connections and input data that is to be
222 * processed. Also check for connections with data queued and whether we can
223 * write it out.
227 * comm_select
229 * Called to do the new-style IO, courtesy of squid (like most of this
230 * new IO code). This routine handles the stuff we've hidden in
231 * comm_setselect and fd_table[] and calls callbacks for IO ready
232 * events.
236 comm_select(unsigned long delay)
238 int num, i;
239 struct dvpoll dopoll;
243 for (;;)
245 dopoll.dp_timeout = delay;
246 dopoll.dp_nfds = maxfd;
247 dopoll.dp_fds = npollfds;
248 num = ioctl(dpfd, DP_POLL, &dopoll);
249 if(num >= 0)
250 break;
251 if(ignoreErrno(errno))
252 break;
253 set_time();
254 return COMM_ERROR;
257 set_time();
258 if(num == 0)
259 continue;
261 for (i = 0; i < num; i++)
263 int fd = dopoll.dp_fds[i].fd;
264 PF *hdl = NULL;
265 fde_t *F = &fd_table[fd];
266 if((dopoll.dp_fds[i].
267 revents & (POLLRDNORM | POLLIN | POLLHUP |
268 POLLERR))
269 && (dopoll.dp_fds[i].events & (POLLRDNORM | POLLIN)))
271 if((hdl = F->read_handler) != NULL)
273 F->read_handler = NULL;
274 hdl(fd, F->read_data);
276 * this call used to be with a NULL pointer, BUT
277 * in the devpoll case we only want to update the
278 * poll set *if* the handler changes state (active ->
279 * NULL or vice versa.)
281 devpoll_update_events(fd,
282 COMM_SELECT_READ, F->read_handler);
284 else
285 ilog(L_IOERROR,
286 "comm_select: Unhandled read event: fdmask: %x",
287 fdmask[fd]);
290 if(F->flags.open == 0)
291 continue; /* Read handler closed us..go on to do something more useful */
292 if((dopoll.dp_fds[i].
293 revents & (POLLWRNORM | POLLOUT | POLLHUP |
294 POLLERR))
295 && (dopoll.dp_fds[i].events & (POLLWRNORM | POLLOUT)))
297 if((hdl = F->write_handler) != NULL)
299 F->write_handler = NULL;
300 hdl(fd, F->write_data);
301 /* See above similar code in the read case */
302 devpoll_update_events(fd,
303 COMM_SELECT_WRITE, F->write_handler);
305 else
306 ilog(L_IOERROR,
307 "comm_select: Unhandled write event: fdmask: %x",
308 fdmask[fd]);
311 if(dopoll.dp_fds[i].revents & POLLNVAL)
313 ilog(L_IOERROR, "revents was Invalid for %d", fd);
316 return COMM_OK;
318 while (0);
319 /* XXX Get here, we broke! */
320 return 0;