ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/libio/comm/select.c
Revision: 59
Committed: Mon Oct 3 15:11:57 2005 UTC (18 years, 6 months ago) by adx
Content type: text/x-csrc
File size: 4847 byte(s)
Log Message:
- move non-irc related sources to /libio
- todo: make it independent of the rest of code

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * s_bsd_select.c: select() compatible network routines.
4 *
5 * Originally by Adrian Chadd <adrian@creative.net.au>
6 * Copyright (C) 2002 Hybrid Development Team
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
22 *
23 * $Id: s_bsd_select.c 33 2005-10-02 20:50:00Z knight $
24 */
25
26 #include "stdinc.h"
27 #include "fdlist.h"
28 #include "hook.h"
29 #include "ircd.h"
30 #include "s_bsd.h"
31 #include "s_log.h"
32
33 /*
34 * Note that this is only a single list - multiple lists is kinda pointless
35 * under select because the list size is a function of the highest FD :-)
36 * -- adrian
37 */
38
39 static fd_set select_readfds, tmpreadfds;
40 static fd_set select_writefds, tmpwritefds;
41 static int highest_fd = -1;
42 static dlink_node *hookptr;
43
44 /*
45 * changing_fdlimit
46 *
47 * Make sure hard_fdlimit doesn't go too big.
48 */
49 static void *
50 changing_fdlimit(va_list args)
51 {
52 int fdmax = va_arg(args, int);
53
54 if (fdmax > FD_SETSIZE)
55 fdmax = FD_SETSIZE;
56
57 return pass_callback(hookptr, fdmax);
58 }
59
60 /*
61 * init_netio
62 *
63 * This is a needed exported function which will be called to initialise
64 * the network loop code.
65 */
66 void
67 init_netio(void)
68 {
69 FD_ZERO(&select_readfds);
70 FD_ZERO(&select_writefds);
71
72 hookptr = install_hook(fdlimit_cb, changing_fdlimit);
73 }
74
75 /*
76 * comm_setselect
77 *
78 * This is a needed exported function which will be called to register
79 * and deregister interest in a pending IO state for a given FD.
80 */
81 void
82 comm_setselect(fde_t *F, unsigned int type, PF *handler,
83 void *client_data, time_t timeout)
84 {
85 int new_events;
86
87 if ((type & COMM_SELECT_READ))
88 {
89 F->read_handler = handler;
90 F->read_data = client_data;
91 }
92
93 if ((type & COMM_SELECT_WRITE))
94 {
95 F->write_handler = handler;
96 F->write_data = client_data;
97 }
98
99 new_events = (F->read_handler ? COMM_SELECT_READ : 0) |
100 (F->write_handler ? COMM_SELECT_WRITE : 0);
101
102 if (timeout != 0)
103 F->timeout = CurrentTime + (timeout / 1000);
104
105 if (new_events != F->evcache)
106 {
107 if ((new_events & COMM_SELECT_READ))
108 FD_SET(F->fd, &select_readfds);
109 else
110 {
111 FD_CLR(F->fd, &select_readfds);
112 FD_CLR(F->fd, &tmpreadfds);
113 }
114
115 if ((new_events & COMM_SELECT_WRITE))
116 FD_SET(F->fd, &select_writefds);
117 else
118 {
119 FD_CLR(F->fd, &select_writefds);
120 FD_CLR(F->fd, &tmpwritefds);
121 }
122
123 if (new_events == 0)
124 {
125 if (highest_fd == F->fd)
126 while (highest_fd >= 0 && (FD_ISSET(highest_fd, &select_readfds) ||
127 FD_ISSET(highest_fd, &select_writefds)))
128 highest_fd--;
129 }
130 else if (F->evcache == 0)
131 if (F->fd > highest_fd)
132 highest_fd = F->fd;
133
134 F->evcache = new_events;
135 }
136 }
137
138 /*
139 * comm_select
140 *
141 * Called to do the new-style IO, courtesy of squid (like most of this
142 * new IO code). This routine handles the stuff we've hidden in
143 * comm_setselect and fd_table[] and calls callbacks for IO ready
144 * events.
145 */
146 void
147 comm_select(void)
148 {
149 struct timeval to;
150 int num, fd;
151 fde_t *F;
152 PF *hdl;
153
154 /* Copy over the read/write sets so we don't have to rebuild em */
155 memcpy(&tmpreadfds, &select_readfds, sizeof(fd_set));
156 memcpy(&tmpwritefds, &select_writefds, sizeof(fd_set));
157
158 to.tv_sec = 0;
159 to.tv_usec = SELECT_DELAY * 1000;
160 num = select(highest_fd + 1, &tmpreadfds, &tmpwritefds, NULL, &to);
161
162 set_time();
163
164 if (num < 0)
165 {
166 #ifdef HAVE_USLEEP
167 usleep(50000);
168 #endif
169 return;
170 }
171
172 for (fd = 0; fd <= highest_fd && num > 0; fd++)
173 if (FD_ISSET(fd, &tmpreadfds) || FD_ISSET(fd, &tmpwritefds))
174 {
175 num--;
176
177 F = lookup_fd(fd);
178 if (F == NULL || !F->flags.open)
179 continue;
180
181 if (FD_ISSET(fd, &tmpreadfds))
182 if ((hdl = F->read_handler) != NULL)
183 {
184 F->read_handler = NULL;
185 hdl(F, F->read_data);
186 if (!F->flags.open)
187 continue;
188 }
189
190 if (FD_ISSET(fd, &tmpwritefds))
191 if ((hdl = F->write_handler) != NULL)
192 {
193 F->write_handler = NULL;
194 hdl(F, F->write_data);
195 if (!F->flags.open)
196 continue;
197 }
198
199 comm_setselect(F, 0, NULL, NULL, 0);
200 }
201 }

Properties

Name Value
svn:eol-style native
svn:keywords "Id Revision"