]> jfr.im git - irc/rqf/shadowircd.git/blame - libratbox/src/select.c
Copied libratbox and related stuff from shadowircd upstream.
[irc/rqf/shadowircd.git] / libratbox / src / select.c
CommitLineData
b57f37fb
WP
1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * select.c: select() 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: select.c 26092 2008-09-19 15:13:52Z androsyn $
b57f37fb 26 */
94b4fbf9 27#define FD_SETSIZE 65535
b57f37fb
WP
28#include <libratbox_config.h>
29#include <ratbox_lib.h>
30#include <commio-int.h>
31
94b4fbf9
VY
32#if defined(HAVE_SELECT) || defined(_WIN32)
33
34#ifdef _WIN32
35#define MY_FD_SET(x, y) FD_SET((SOCKET)x, y)
36#define MY_FD_CLR(x, y) FD_CLR((SOCKET)x, y)
37#else
38#define MY_FD_SET(x, y) FD_SET(x, y)
39#define MY_FD_CLR(x, y) FD_CLR(x, y)
40#endif
b57f37fb
WP
41
42#ifdef HAVE_SYS_SELECT_H
43#include <sys/select.h>
44#endif
45/*
46 * Note that this is only a single list - multiple lists is kinda pointless
47 * under select because the list size is a function of the highest FD :-)
48 * -- adrian
49 */
50
51static fd_set select_readfds;
52static fd_set select_writefds;
53
54/*
55 * You know, I'd rather have these local to rb_select but for some
56 * reason my gcc decides that I can't modify them at all..
57 * -- adrian
58 */
59static fd_set tmpreadfds;
60static fd_set tmpwritefds;
61
62static int rb_maxfd = -1;
63static void select_update_selectfds(rb_fde_t *F, short event, PF * handler);
64
65/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
66/* Private functions */
67
68/*
69 * set and clear entries in the select array ..
70 */
71static void
72select_update_selectfds(rb_fde_t *F, short event, PF * handler)
73{
74 /* Update the read / write set */
75 if(event & RB_SELECT_READ)
76 {
94b4fbf9 77 if(handler)
b57f37fb 78 {
94b4fbf9
VY
79 MY_FD_SET(F->fd, &select_readfds);
80 F->pflags |= RB_SELECT_READ;
81 }
82 else
b57f37fb 83 {
94b4fbf9 84 MY_FD_CLR(F->fd, &select_readfds);
b57f37fb
WP
85 F->pflags &= ~RB_SELECT_READ;
86 }
87 }
88
89 if(event & RB_SELECT_WRITE)
90 {
94b4fbf9 91 if(handler)
b57f37fb 92 {
94b4fbf9 93 MY_FD_SET(F->fd, &select_writefds);
b57f37fb
WP
94 F->pflags |= RB_SELECT_WRITE;
95 }
94b4fbf9 96 else
b57f37fb 97 {
94b4fbf9 98 MY_FD_CLR(F->fd, &select_writefds);
b57f37fb
WP
99 F->pflags &= ~RB_SELECT_WRITE;
100 }
101 }
102
94b4fbf9 103 if(F->pflags & (RB_SELECT_READ | RB_SELECT_WRITE))
b57f37fb
WP
104 {
105 if(F->fd > rb_maxfd)
106 {
94b4fbf9 107 rb_maxfd = F->fd;
b57f37fb 108 }
94b4fbf9 109 }
b57f37fb
WP
110 else if(F->fd <= rb_maxfd)
111 {
94b4fbf9
VY
112 while(rb_maxfd >= 0 && !FD_ISSET(rb_maxfd, &select_readfds)
113 && !FD_ISSET(rb_maxfd, &select_writefds))
114 rb_maxfd--;
b57f37fb
WP
115 }
116}
117
118
119/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
120/* Public functions */
121
122int
123rb_setup_fd_select(rb_fde_t *F)
124{
94b4fbf9 125 return 0;
b57f37fb
WP
126}
127
128
129/*
130 * rb_init_netio
131 *
132 * This is a needed exported function which will be called to initialise
133 * the network loop code.
134 */
94b4fbf9 135extern int rb_maxconnections;
b57f37fb
WP
136int
137rb_init_netio_select(void)
138{
94b4fbf9
VY
139 if(rb_maxconnections > FD_SETSIZE)
140 rb_maxconnections = FD_SETSIZE; /* override this */
b57f37fb
WP
141 FD_ZERO(&select_readfds);
142 FD_ZERO(&select_writefds);
143 return 0;
144}
145
146/*
147 * rb_setselect
148 *
149 * This is a needed exported function which will be called to register
150 * and deregister interest in a pending IO state for a given FD.
151 */
152void
94b4fbf9 153rb_setselect_select(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
b57f37fb
WP
154{
155 lrb_assert(IsFDOpen(F));
156
157 if(type & RB_SELECT_READ)
158 {
159 F->read_handler = handler;
160 F->read_data = client_data;
161 select_update_selectfds(F, RB_SELECT_READ, handler);
162 }
163 if(type & RB_SELECT_WRITE)
164 {
165 F->write_handler = handler;
166 F->write_data = client_data;
167 select_update_selectfds(F, RB_SELECT_WRITE, handler);
168 }
169}
170
171/*
172 * Check all connections for new connections and input data that is to be
173 * processed. Also check for connections with data queued and whether we can
174 * write it out.
175 */
176
177/*
178 * rb_select
179 *
180 * Do IO events
181 */
182
183int
184rb_select_select(long delay)
185{
186 int num;
187 int fd;
188 PF *hdl;
189 rb_fde_t *F;
190 struct timeval to;
191
192 /* Copy over the read/write sets so we don't have to rebuild em */
193 memcpy(&tmpreadfds, &select_readfds, sizeof(fd_set));
194 memcpy(&tmpwritefds, &select_writefds, sizeof(fd_set));
195
94b4fbf9 196 for(;;)
b57f37fb
WP
197 {
198 to.tv_sec = 0;
199 to.tv_usec = delay * 1000;
200 num = select(rb_maxfd + 1, &tmpreadfds, &tmpwritefds, NULL, &to);
201 if(num >= 0)
202 break;
203 if(rb_ignore_errno(errno))
204 continue;
205 rb_set_time();
206 /* error! */
207 return -1;
208 /* NOTREACHED */
209 }
210 rb_set_time();
211
212 if(num == 0)
213 return 0;
214
215 /* XXX we *could* optimise by falling out after doing num fds ... */
94b4fbf9 216 for(fd = 0; fd < rb_maxfd + 1; fd++)
b57f37fb
WP
217 {
218 F = rb_find_fd(fd);
219 if(F == NULL)
220 continue;
221 if(FD_ISSET(fd, &tmpreadfds))
222 {
223 hdl = F->read_handler;
224 F->read_handler = NULL;
225 if(hdl)
226 hdl(F, F->read_data);
227 }
228
229 if(!IsFDOpen(F))
230 continue; /* Read handler closed us..go on */
231
232 if(FD_ISSET(fd, &tmpwritefds))
233 {
234 hdl = F->write_handler;
235 F->write_handler = NULL;
236 if(hdl)
237 hdl(F, F->write_data);
238 }
239
240 if(F->read_handler == NULL)
241 select_update_selectfds(F, RB_SELECT_READ, NULL);
242 if(F->write_handler == NULL)
243 select_update_selectfds(F, RB_SELECT_WRITE, NULL);
244 }
245 return 0;
246}
247
248#else /* select not supported..what sort of garbage is this? */
94b4fbf9 249int
b57f37fb
WP
250rb_init_netio_select(void)
251{
252 return ENOSYS;
253}
254
255void
256rb_setselect_select(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
257{
94b4fbf9
VY
258 errno = ENOSYS;
259 return;
b57f37fb 260}
94b4fbf9 261
b57f37fb
WP
262int
263rb_select_select(long delay)
264{
94b4fbf9
VY
265 errno = ENOSYS;
266 return -1;
b57f37fb 267}
94b4fbf9 268
b57f37fb
WP
269int
270rb_setup_fd_select(rb_fde_t *F)
271{
94b4fbf9
VY
272 errno = ENOSYS;
273 return -1;
b57f37fb
WP
274}
275
276#endif