]> jfr.im git - irc/rqf/shadowircd.git/blob - libratbox/src/poll.c
Fix up grammar in ShadowIRCd MOTD for great good!
[irc/rqf/shadowircd.git] / libratbox / src / poll.c
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * s_bsd_poll.c: POSIX 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 *
25 */
26 #include <libratbox_config.h>
27 #include <ratbox_lib.h>
28 #include <commio-int.h>
29
30 #if defined(HAVE_POLL) && (HAVE_SYS_POLL_H)
31 #include <sys/poll.h>
32
33
34 /* I hate linux -- adrian */
35 #ifndef POLLRDNORM
36 #define POLLRDNORM POLLIN
37 #endif
38 #ifndef POLLWRNORM
39 #define POLLWRNORM POLLOUT
40 #endif
41
42 struct _pollfd_list
43 {
44 struct pollfd *pollfds;
45 int maxindex; /* highest FD number */
46 int allocated; /* number of pollfds allocated */
47 };
48
49 typedef struct _pollfd_list pollfd_list_t;
50
51 static pollfd_list_t pollfd_list;
52
53 int
54 rb_setup_fd_poll(rb_fde_t *F)
55 {
56 return 0;
57 }
58
59
60 /*
61 * rb_init_netio
62 *
63 * This is a needed exported function which will be called to initialise
64 * the network loop code.
65 */
66 int
67 rb_init_netio_poll(void)
68 {
69 int fd;
70 pollfd_list.pollfds = rb_malloc(rb_getmaxconnect() * (sizeof(struct pollfd)));
71 pollfd_list.allocated = rb_getmaxconnect();
72 for(fd = 0; fd < rb_getmaxconnect(); fd++)
73 {
74 pollfd_list.pollfds[fd].fd = -1;
75 }
76 pollfd_list.maxindex = 0;
77 return 0;
78 }
79
80 static void
81 resize_pollarray(int fd)
82 {
83 if(rb_unlikely(fd >= pollfd_list.allocated))
84 {
85 int x, old_value = pollfd_list.allocated;
86 pollfd_list.allocated += 1024;
87 pollfd_list.pollfds =
88 rb_realloc(pollfd_list.pollfds,
89 pollfd_list.allocated * (sizeof(struct pollfd)));
90 memset(&pollfd_list.pollfds[old_value + 1], 0, sizeof(struct pollfd) * 1024);
91 for(x = old_value + 1; x < pollfd_list.allocated; x++)
92 {
93 pollfd_list.pollfds[x].fd = -1;
94 }
95 }
96 }
97
98 /*
99 * rb_setselect
100 *
101 * This is a needed exported function which will be called to register
102 * and deregister interest in a pending IO state for a given FD.
103 */
104 void
105 rb_setselect_poll(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
106 {
107 if(F == NULL)
108 return;
109
110 if(type & RB_SELECT_READ)
111 {
112 F->read_handler = handler;
113 F->read_data = client_data;
114 if(handler != NULL)
115 F->pflags |= POLLRDNORM;
116 else
117 F->pflags &= ~POLLRDNORM;
118 }
119 if(type & RB_SELECT_WRITE)
120 {
121 F->write_handler = handler;
122 F->write_data = client_data;
123 if(handler != NULL)
124 F->pflags |= POLLWRNORM;
125 else
126 F->pflags &= ~POLLWRNORM;
127 }
128 resize_pollarray(F->fd);
129
130 if(F->pflags <= 0)
131 {
132 pollfd_list.pollfds[F->fd].events = 0;
133 pollfd_list.pollfds[F->fd].fd = -1;
134 if(F->fd == pollfd_list.maxindex)
135 {
136 while(pollfd_list.maxindex >= 0
137 && pollfd_list.pollfds[pollfd_list.maxindex].fd == -1)
138 pollfd_list.maxindex--;
139 }
140 }
141 else
142 {
143 pollfd_list.pollfds[F->fd].events = F->pflags;
144 pollfd_list.pollfds[F->fd].fd = F->fd;
145 if(F->fd > pollfd_list.maxindex)
146 pollfd_list.maxindex = F->fd;
147 }
148
149 }
150
151 /* int rb_select(unsigned long delay)
152 * Input: The maximum time to delay.
153 * Output: Returns -1 on error, 0 on success.
154 * Side-effects: Deregisters future interest in IO and calls the handlers
155 * if an event occurs for an FD.
156 * Comments: Check all connections for new connections and input data
157 * that is to be processed. Also check for connections with data queued
158 * and whether we can write it out.
159 * Called to do the new-style IO, courtesy of squid (like most of this
160 * new IO code). This routine handles the stuff we've hidden in
161 * rb_setselect and fd_table[] and calls callbacks for IO ready
162 * events.
163 */
164
165 int
166 rb_select_poll(long delay)
167 {
168 int num;
169 int fd;
170 int ci;
171 PF *hdl;
172 void *data;
173 struct pollfd *pfd;
174 int revents;
175
176 num = poll(pollfd_list.pollfds, pollfd_list.maxindex + 1, delay);
177 rb_set_time();
178 if(num < 0)
179 {
180 if(!rb_ignore_errno(errno))
181 return RB_OK;
182 else
183 return RB_ERROR;
184 }
185 if(num == 0)
186 return RB_OK;
187
188 /* XXX we *could* optimise by falling out after doing num fds ... */
189 for(ci = 0; ci < pollfd_list.maxindex + 1; ci++)
190 {
191 rb_fde_t *F;
192 pfd = &pollfd_list.pollfds[ci];
193
194 revents = pfd->revents;
195 fd = pfd->fd;
196 if(revents == 0 || fd == -1)
197 continue;
198
199 F = rb_find_fd(fd);
200 if(F == NULL)
201 continue;
202
203 if(revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
204 {
205 hdl = F->read_handler;
206 data = F->read_data;
207 F->read_handler = NULL;
208 F->read_data = NULL;
209 if(hdl)
210 hdl(F, data);
211 }
212
213 if(IsFDOpen(F) && (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)))
214 {
215 hdl = F->write_handler;
216 data = F->write_data;
217 F->write_handler = NULL;
218 F->write_data = NULL;
219 if(hdl)
220 hdl(F, data);
221 }
222
223 if(F->read_handler == NULL)
224 rb_setselect_poll(F, RB_SELECT_READ, NULL, NULL);
225 if(F->write_handler == NULL)
226 rb_setselect_poll(F, RB_SELECT_WRITE, NULL, NULL);
227
228 }
229 return 0;
230 }
231
232 #else /* poll not supported */
233 int
234 rb_init_netio_poll(void)
235 {
236 errno = ENOSYS;
237 return -1;
238 }
239
240 void
241 rb_setselect_poll(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
242 {
243 errno = ENOSYS;
244 return;
245 }
246
247 int
248 rb_select_poll(long delay)
249 {
250 errno = ENOSYS;
251 return -1;
252 }
253
254 int
255 rb_setup_fd_poll(rb_fde_t *F)
256 {
257 errno = ENOSYS;
258 return -1;
259 }
260
261 #endif