]> jfr.im git - irc/rqf/shadowircd.git/blame - libcharybdis/select.c
[svn] Repair operspy who !#channel, broken by me in r3283.
[irc/rqf/shadowircd.git] / libcharybdis / select.c
CommitLineData
212380e3 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 * USA
24 *
e70f8e92 25 * $Id: select.c 3229 2007-03-05 17:23:07Z nenolod $
212380e3 26 */
27
28#include "config.h"
29
30#include "libcharybdis.h"
31
32#if HARD_FDLIMIT_ >= FD_SETSIZE
33#error HARD_FDLIMIT_ must be less than FD_SETSIZE(try using poll instead of select)
34#endif
35/*
36 * Note that this is only a single list - multiple lists is kinda pointless
37 * under select because the list size is a function of the highest FD :-)
38 * -- adrian
39 */
40
41fd_set select_readfds;
42fd_set select_writefds;
43
44/*
45 * You know, I'd rather have these local to comm_select but for some
46 * reason my gcc decides that I can't modify them at all..
47 * -- adrian
48 */
49fd_set tmpreadfds;
50fd_set tmpwritefds;
51
52static void select_update_selectfds(int fd, short event, PF * handler);
53
54/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
55/* Private functions */
56
57/*
58 * set and clear entries in the select array ..
59 */
60static void
61select_update_selectfds(int fd, short event, PF * handler)
62{
63 /* Update the read / write set */
64 if(event & COMM_SELECT_READ)
65 {
66 if(handler)
67 FD_SET(fd, &select_readfds);
68 else
69 FD_CLR(fd, &select_readfds);
70 }
71 if(event & COMM_SELECT_WRITE)
72 {
73 if(handler)
74 FD_SET(fd, &select_writefds);
75 else
76 FD_CLR(fd, &select_writefds);
77 }
78}
79
80
81/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
82/* Public functions */
83
84
85/*
86 * init_netio
87 *
88 * This is a needed exported function which will be called to initialise
89 * the network loop code.
90 */
91void
92init_netio(void)
93{
94 FD_ZERO(&select_readfds);
95 FD_ZERO(&select_writefds);
96}
97
98/*
99 * comm_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 */
104void
105comm_setselect(int fd, fdlist_t list, unsigned int type, PF * handler,
106 void *client_data, time_t timeout)
107{
e70f8e92 108 fde_t *F = comm_locate_fd(fd);
212380e3 109 s_assert(fd >= 0);
110 s_assert(F->flags.open);
111
112 if(type & COMM_SELECT_READ)
113 {
114 F->read_handler = handler;
115 F->read_data = client_data;
116 select_update_selectfds(fd, COMM_SELECT_READ, handler);
117 }
118 if(type & COMM_SELECT_WRITE)
119 {
120 F->write_handler = handler;
121 F->write_data = client_data;
122 select_update_selectfds(fd, COMM_SELECT_WRITE, handler);
123 }
124 if(timeout)
125 F->timeout = CurrentTime + (timeout / 1000);
126}
127
128/*
129 * Check all connections for new connections and input data that is to be
130 * processed. Also check for connections with data queued and whether we can
131 * write it out.
132 */
133
134/*
135 * comm_select
136 *
137 * Do IO events
138 */
139
140int
141comm_select(unsigned long delay)
142{
143 int num;
144 int fd;
145 PF *hdl;
146 fde_t *F;
147 struct timeval to;
148
149 /* Copy over the read/write sets so we don't have to rebuild em */
150 memcpy(&tmpreadfds, &select_readfds, sizeof(fd_set));
151 memcpy(&tmpwritefds, &select_writefds, sizeof(fd_set));
152
153 for (;;)
154 {
155 to.tv_sec = 0;
156 to.tv_usec = delay * 1000;
157 num = select(highest_fd + 1, &tmpreadfds, &tmpwritefds, NULL, &to);
158 if(num >= 0)
159 break;
160 if(ignoreErrno(errno))
161 continue;
162 set_time();
163 /* error! */
164 return -1;
165 /* NOTREACHED */
166 }
167 set_time();
168
169 if(num == 0)
170 return 0;
171
172 /* XXX we *could* optimise by falling out after doing num fds ... */
173 for (fd = 0; fd < highest_fd + 1; fd++)
174 {
e70f8e92 175 F = comm_locate_fd(fd);
212380e3 176
177 if(FD_ISSET(fd, &tmpreadfds))
178 {
179 hdl = F->read_handler;
180 F->read_handler = NULL;
181 if(hdl)
182 hdl(fd, F->read_data);
183 }
184
185 if(F->flags.open == 0)
186 continue; /* Read handler closed us..go on */
187
188 if(FD_ISSET(fd, &tmpwritefds))
189 {
190 hdl = F->write_handler;
191 F->write_handler = NULL;
192 if(hdl)
193 hdl(fd, F->write_data);
194 }
195
196 if(F->read_handler == NULL)
197 select_update_selectfds(fd, COMM_SELECT_READ, NULL);
198 if(F->write_handler == NULL)
199 select_update_selectfds(fd, COMM_SELECT_WRITE, NULL);
200 }
201 return 0;
202}
203