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