]> jfr.im git - irc/rqf/shadowircd.git/blame - libratbox/src/poll.c
Copied libratbox and related stuff from shadowircd upstream.
[irc/rqf/shadowircd.git] / libratbox / src / poll.c
CommitLineData
b57f37fb
WP
1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * s_bsd_poll.c: POSIX poll() 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 *
94b4fbf9 25 * $Id: poll.c 26092 2008-09-19 15:13:52Z androsyn $
b57f37fb
WP
26 */
27#include <libratbox_config.h>
28#include <ratbox_lib.h>
29#include <commio-int.h>
30
31#if defined(HAVE_POLL) && (HAVE_SYS_POLL_H)
32#include <sys/poll.h>
33
34
35/* I hate linux -- adrian */
36#ifndef POLLRDNORM
37#define POLLRDNORM POLLIN
38#endif
39#ifndef POLLWRNORM
40#define POLLWRNORM POLLOUT
41#endif
42
43struct _pollfd_list
44{
45 struct pollfd *pollfds;
46 int maxindex; /* highest FD number */
47 int allocated; /* number of pollfds allocated */
48};
49
50typedef struct _pollfd_list pollfd_list_t;
51
52static pollfd_list_t pollfd_list;
53
54int
94b4fbf9 55rb_setup_fd_poll(rb_fde_t *F)
b57f37fb
WP
56{
57 return 0;
58}
59
60
61/*
62 * rb_init_netio
63 *
64 * This is a needed exported function which will be called to initialise
65 * the network loop code.
66 */
67int
68rb_init_netio_poll(void)
69{
70 int fd;
71 pollfd_list.pollfds = rb_malloc(rb_getmaxconnect() * (sizeof(struct pollfd)));
72 pollfd_list.allocated = rb_getmaxconnect();
94b4fbf9 73 for(fd = 0; fd < rb_getmaxconnect(); fd++)
b57f37fb
WP
74 {
75 pollfd_list.pollfds[fd].fd = -1;
76 }
77 pollfd_list.maxindex = 0;
78 return 0;
79}
80
81static void
82resize_pollarray(int fd)
83{
033be687 84 if(rb_unlikely(fd >= pollfd_list.allocated))
b57f37fb
WP
85 {
86 int x, old_value = pollfd_list.allocated;
87 pollfd_list.allocated += 1024;
88 pollfd_list.pollfds =
89 rb_realloc(pollfd_list.pollfds,
90 pollfd_list.allocated * (sizeof(struct pollfd)));
91 memset(&pollfd_list.pollfds[old_value + 1], 0, sizeof(struct pollfd) * 1024);
94b4fbf9 92 for(x = old_value + 1; x < pollfd_list.allocated; x++)
b57f37fb
WP
93 {
94 pollfd_list.pollfds[x].fd = -1;
95 }
96 }
97}
98
99/*
100 * rb_setselect
101 *
102 * This is a needed exported function which will be called to register
103 * and deregister interest in a pending IO state for a given FD.
104 */
105void
94b4fbf9 106rb_setselect_poll(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
b57f37fb
WP
107{
108 if(F == NULL)
109 return;
110
111 if(type & RB_SELECT_READ)
112 {
113 F->read_handler = handler;
114 F->read_data = client_data;
115 if(handler != NULL)
116 F->pflags |= POLLRDNORM;
117 else
118 F->pflags &= ~POLLRDNORM;
119 }
120 if(type & RB_SELECT_WRITE)
121 {
122 F->write_handler = handler;
123 F->write_data = client_data;
124 if(handler != NULL)
125 F->pflags |= POLLWRNORM;
126 else
127 F->pflags &= ~POLLWRNORM;
128 }
129 resize_pollarray(F->fd);
130
131 if(F->pflags <= 0)
132 {
133 pollfd_list.pollfds[F->fd].events = 0;
134 pollfd_list.pollfds[F->fd].fd = -1;
135 if(F->fd == pollfd_list.maxindex)
136 {
94b4fbf9
VY
137 while(pollfd_list.maxindex >= 0
138 && pollfd_list.pollfds[pollfd_list.maxindex].fd == -1)
b57f37fb
WP
139 pollfd_list.maxindex--;
140 }
141 }
142 else
143 {
144 pollfd_list.pollfds[F->fd].events = F->pflags;
145 pollfd_list.pollfds[F->fd].fd = F->fd;
146 if(F->fd > pollfd_list.maxindex)
147 pollfd_list.maxindex = F->fd;
148 }
149
150}
151
152/* int rb_select(unsigned long delay)
153 * Input: The maximum time to delay.
154 * Output: Returns -1 on error, 0 on success.
155 * Side-effects: Deregisters future interest in IO and calls the handlers
156 * if an event occurs for an FD.
157 * Comments: Check all connections for new connections and input data
158 * that is to be processed. Also check for connections with data queued
159 * and whether we can write it out.
160 * Called to do the new-style IO, courtesy of squid (like most of this
161 * new IO code). This routine handles the stuff we've hidden in
162 * rb_setselect and fd_table[] and calls callbacks for IO ready
163 * events.
164 */
165
166int
167rb_select_poll(long delay)
168{
169 int num;
170 int fd;
171 int ci;
172 PF *hdl;
173 void *data;
174 struct pollfd *pfd;
175 int revents;
176
177 num = poll(pollfd_list.pollfds, pollfd_list.maxindex + 1, delay);
94b4fbf9 178 rb_set_time();
b57f37fb
WP
179 if(num < 0)
180 {
181 if(!rb_ignore_errno(errno))
182 return RB_OK;
183 else
184 return RB_ERROR;
185 }
186 if(num == 0)
94b4fbf9
VY
187 return RB_OK;
188
b57f37fb 189 /* XXX we *could* optimise by falling out after doing num fds ... */
94b4fbf9 190 for(ci = 0; ci < pollfd_list.maxindex + 1; ci++)
b57f37fb
WP
191 {
192 rb_fde_t *F;
193 pfd = &pollfd_list.pollfds[ci];
194
195 revents = pfd->revents;
94b4fbf9 196 fd = pfd->fd;
b57f37fb
WP
197 if(revents == 0 || fd == -1)
198 continue;
199
200 F = rb_find_fd(fd);
201 if(F == NULL)
202 continue;
94b4fbf9 203
b57f37fb
WP
204 if(revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
205 {
206 hdl = F->read_handler;
207 data = F->read_data;
208 F->read_handler = NULL;
209 F->read_data = NULL;
210 if(hdl)
211 hdl(F, data);
212 }
213
214 if(IsFDOpen(F) && (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)))
215 {
216 hdl = F->write_handler;
217 data = F->write_data;
218 F->write_handler = NULL;
219 F->write_data = NULL;
94b4fbf9 220 if(hdl)
b57f37fb
WP
221 hdl(F, data);
222 }
223
224 if(F->read_handler == NULL)
225 rb_setselect_poll(F, RB_SELECT_READ, NULL, NULL);
226 if(F->write_handler == NULL)
227 rb_setselect_poll(F, RB_SELECT_WRITE, NULL, NULL);
94b4fbf9 228
b57f37fb
WP
229 }
230 return 0;
231}
232
233#else /* poll not supported */
234int
235rb_init_netio_poll(void)
236{
237 errno = ENOSYS;
238 return -1;
239}
240
241void
94b4fbf9 242rb_setselect_poll(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
b57f37fb
WP
243{
244 errno = ENOSYS;
245 return;
246}
247
248int
249rb_select_poll(long delay)
250{
251 errno = ENOSYS;
252 return -1;
253}
254
255int
94b4fbf9 256rb_setup_fd_poll(rb_fde_t *F)
b57f37fb
WP
257{
258 errno = ENOSYS;
259 return -1;
260}
261
262#endif