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