Clean a bit - to be continued...
[seven-1.x.git] / libseven / devpoll.c
blob876e4fac139551182a42774c2cb82dce6a76a0ba
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
27 #include "config.h"
29 #include "stdinc.h"
30 #include <sys/devpoll.h>
32 #include "libseven.h"
34 #define POLL_LENGTH HARD_FDLIMIT
37 static void devpoll_update_events(int, short, PF *);
38 static int dpfd;
39 static short fdmask[POLL_LENGTH];
40 static void devpoll_update_events(int, short, PF *);
41 static void devpoll_write_update(int, int);
43 /* #define NOTYET 1 */
45 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
46 /* Private functions */
49 * Write an update to the devpoll filter.
50 * See, we end up having to do a seperate (?) remove before we do an
51 * add of a new polltype, so we have to have this function seperate from
52 * the others.
54 static void
55 devpoll_write_update(int fd, int events)
57 struct pollfd pollfds[1]; /* Just to be careful */
58 int retval;
60 /* Build the pollfd entry */
61 pollfds[0].revents = 0;
62 pollfds[0].fd = fd;
63 pollfds[0].events = events;
65 /* Write the thing to our poll fd */
66 retval = write(dpfd, &pollfds[0], sizeof(struct pollfd));
67 if(retval != sizeof(struct pollfd))
68 libseven_log("devpoll_write_update: dpfd write failed %d: %s", errno, strerror(errno));
69 /* Done! */
72 void
73 devpoll_update_events(int fd, short filter, PF * handler)
75 int update_required = 0;
76 int cur_mask = fdmask[fd];
77 PF *cur_handler;
78 fdmask[fd] = 0;
79 switch (filter)
81 case COMM_SELECT_READ:
82 cur_handler = fd_table[fd].read_handler;
83 if(handler)
84 fdmask[fd] |= POLLRDNORM;
85 else
86 fdmask[fd] &= ~POLLRDNORM;
87 if(fd_table[fd].write_handler)
88 fdmask[fd] |= POLLWRNORM;
89 break;
90 case COMM_SELECT_WRITE:
91 cur_handler = fd_table[fd].write_handler;
92 if(handler)
93 fdmask[fd] |= POLLWRNORM;
94 else
95 fdmask[fd] &= ~POLLWRNORM;
96 if(fd_table[fd].read_handler)
97 fdmask[fd] |= POLLRDNORM;
98 break;
99 default:
100 #ifdef NOTYET
101 libseven_log("devpoll_update_events called with unknown filter: %hd", filter);
102 #endif
103 return;
104 break;
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)
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.
120 if(fdmask[fd])
122 devpoll_write_update(fd, POLLREMOVE);
123 devpoll_write_update(fd, fdmask[fd]);
125 else
126 devpoll_write_update(fd, POLLREMOVE);
134 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
135 /* Public functions */
139 * init_netio
141 * This is a needed exported function which will be called to initialise
142 * the network loop code.
144 void
145 init_netio(void)
147 memset(&fdmask, 0, sizeof(fdmask));
148 dpfd = open("/dev/poll", O_RDWR);
149 if(dpfd < 0)
151 fprintf(stderr,
152 "init_netio: Couldn't open /dev/poll - %d: %s\n",
153 errno, strerror(errno));
154 exit(115); /* Whee! */
159 * comm_setselect
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.
164 void
165 comm_setselect(int fd, fdlist_t list, unsigned int type, PF * handler,
166 void *client_data, time_t timeout)
168 fde_t *F = &fd_table[fd];
169 s_assert(fd >= 0);
170 s_assert(F->flags.open);
172 /* Update the list, even though we're not using it .. */
173 F->list = list;
175 if(type & COMM_SELECT_READ)
177 devpoll_update_events(fd, COMM_SELECT_READ, handler);
178 F->read_handler = handler;
179 F->read_data = client_data;
181 if(type & COMM_SELECT_WRITE)
183 devpoll_update_events(fd, COMM_SELECT_WRITE, handler);
184 F->write_handler = handler;
185 F->write_data = client_data;
187 if(timeout)
188 F->timeout = CurrentTime + (timeout / 1000);
192 * Check all connections for new connections and input data that is to be
193 * processed. Also check for connections with data queued and whether we can
194 * write it out.
198 * comm_select
200 * Called to do the new-style IO, courtesy of squid (like most of this
201 * new IO code). This routine handles the stuff we've hidden in
202 * comm_setselect and fd_table[] and calls callbacks for IO ready
203 * events.
207 comm_select(unsigned long delay)
209 int num, i;
210 struct pollfd pollfds[POLL_LENGTH];
211 struct dvpoll dopoll;
215 for (;;)
217 dopoll.dp_timeout = delay;
218 dopoll.dp_nfds = POLL_LENGTH;
219 dopoll.dp_fds = &pollfds[0];
220 num = ioctl(dpfd, DP_POLL, &dopoll);
221 if(num >= 0)
222 break;
223 if(ignoreErrno(errno))
224 break;
225 set_time();
226 return COMM_ERROR;
229 set_time();
230 if(num == 0)
231 continue;
233 for (i = 0; i < num; i++)
235 int fd = dopoll.dp_fds[i].fd;
236 PF *hdl = NULL;
237 fde_t *F = &fd_table[fd];
238 if((dopoll.dp_fds[i].
239 revents & (POLLRDNORM | POLLIN | POLLHUP |
240 POLLERR))
241 && (dopoll.dp_fds[i].events & (POLLRDNORM | POLLIN)))
243 if((hdl = F->read_handler) != NULL)
245 F->read_handler = NULL;
246 hdl(fd, F->read_data);
248 * this call used to be with a NULL pointer, BUT
249 * in the devpoll case we only want to update the
250 * poll set *if* the handler changes state (active ->
251 * NULL or vice versa.)
253 devpoll_update_events(fd,
254 COMM_SELECT_READ, F->read_handler);
256 else
257 libseven_log("comm_select: Unhandled read event: fdmask: %x",
258 fdmask[fd]);
261 if(F->flags.open == 0)
262 continue; /* Read handler closed us..go on to do something more useful */
263 if((dopoll.dp_fds[i].
264 revents & (POLLWRNORM | POLLOUT | POLLHUP |
265 POLLERR))
266 && (dopoll.dp_fds[i].events & (POLLWRNORM | POLLOUT)))
268 if((hdl = F->write_handler) != NULL)
270 F->write_handler = NULL;
271 hdl(fd, F->write_data);
272 /* See above similar code in the read case */
273 devpoll_update_events(fd,
274 COMM_SELECT_WRITE, F->write_handler);
276 else
277 libseven_log("comm_select: Unhandled write event: fdmask: %x",
278 fdmask[fd]);
281 if(dopoll.dp_fds[i].revents & POLLNVAL)
283 libseven_log("revents was Invalid for %d", fd);
286 return COMM_OK;
288 while (0);
289 /* XXX Get here, we broke! */
290 return 0;