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