2 * ircd-ratbox: A slightly useful ircd.
3 * s_bsd_poll.c: POSIX poll() compatible network routines.
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
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.
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.
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
33 /* I hate linux -- adrian */
35 #define POLLRDNORM POLLIN
38 #define POLLWRNORM POLLOUT
43 struct pollfd pollfds
[MAXCONNECTIONS
];
44 int maxindex
; /* highest FD number */
47 typedef struct _pollfd_list pollfd_list_t
;
49 pollfd_list_t pollfd_list
;
50 static void poll_update_pollfds(int, short, PF
*);
51 static unsigned long last_count
= 0;
52 static unsigned long empty_count
= 0;
53 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
54 /* Private functions */
57 * find a spare slot in the fd list. We can optimise this out later!
64 for (i
= 0; i
< MAXCONNECTIONS
; i
++)
66 if(pollfd_list
.pollfds
[i
].fd
== -1)
78 * set and clear entries in the pollfds[] array.
81 poll_update_pollfds(int fd
, short event
, PF
* handler
)
83 fde_t
*F
= &fd_table
[fd
];
88 F
->comm_index
= poll_findslot();
90 comm_index
= F
->comm_index
;
92 /* Update the events */
95 F
->list
= FDLIST_IDLECLIENT
;
96 pollfd_list
.pollfds
[comm_index
].events
|= event
;
97 pollfd_list
.pollfds
[comm_index
].fd
= fd
;
98 /* update maxindex here */
99 if(comm_index
> pollfd_list
.maxindex
)
100 pollfd_list
.maxindex
= comm_index
;
106 pollfd_list
.pollfds
[comm_index
].events
&= ~event
;
107 if(pollfd_list
.pollfds
[comm_index
].events
== 0)
109 pollfd_list
.pollfds
[comm_index
].fd
= -1;
110 pollfd_list
.pollfds
[comm_index
].revents
= 0;
112 F
->list
= FDLIST_NONE
;
114 /* update pollfd_list.maxindex here */
115 if(comm_index
== pollfd_list
.maxindex
)
116 while (pollfd_list
.maxindex
>= 0 &&
117 pollfd_list
.pollfds
[pollfd_list
.maxindex
].fd
== -1)
118 pollfd_list
.maxindex
--;
125 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
126 /* Public functions */
132 * This is a needed exported function which will be called to initialise
133 * the network loop code.
140 for (fd
= 0; fd
< MAXCONNECTIONS
; fd
++)
142 pollfd_list
.pollfds
[fd
].fd
= -1;
144 pollfd_list
.maxindex
= 0;
150 * This is a needed exported function which will be called to register
151 * and deregister interest in a pending IO state for a given FD.
154 comm_setselect(int fd
, fdlist_t list
, unsigned int type
, PF
* handler
,
155 void *client_data
, time_t timeout
)
157 fde_t
*F
= &fd_table
[fd
];
159 s_assert(F
->flags
.open
);
161 if(type
& COMM_SELECT_READ
)
163 F
->read_handler
= handler
;
164 F
->read_data
= client_data
;
165 poll_update_pollfds(fd
, POLLRDNORM
, handler
);
167 if(type
& COMM_SELECT_WRITE
)
169 F
->write_handler
= handler
;
170 F
->write_data
= client_data
;
171 poll_update_pollfds(fd
, POLLWRNORM
, handler
);
174 F
->timeout
= CurrentTime
+ (timeout
/ 1000);
178 irc_sleep(unsigned long useconds
)
180 #ifdef HAVE_NANOSLEEP
182 t
.tv_sec
= useconds
/ (unsigned long) 1000000;
183 t
.tv_nsec
= (useconds
% (unsigned long) 1000000) * 1000;
184 nanosleep(&t
, (struct timespec
*) NULL
);
188 t
.tv_usec
= useconds
;
189 select(0, NULL
, NULL
, NULL
, &t
);
194 /* int comm_select_fdlist(unsigned long delay)
195 * Input: The maximum time to delay.
196 * Output: Returns -1 on error, 0 on success.
197 * Side-effects: Deregisters future interest in IO and calls the handlers
198 * if an event occurs for an FD.
199 * Comments: Check all connections for new connections and input data
200 * that is to be processed. Also check for connections with data queued
201 * and whether we can write it out.
202 * Called to do the new-style IO, courtesy of squid (like most of this
203 * new IO code). This routine handles the stuff we've hidden in
204 * comm_setselect and fd_table[] and calls callbacks for IO ready
208 comm_select(unsigned long delay
)
213 unsigned long ndelay
;
222 ndelay
= ++empty_count
* 15000 ;
223 if(ndelay
> delay
* 1000)
224 ndelay
= delay
* 1000;
229 /* XXX kill that +1 later ! -- adrian */
232 last_count
= num
= poll(pollfd_list
.pollfds
, pollfd_list
.maxindex
+ 1, 0);
235 if(ignoreErrno(errno
))
243 /* update current time again, eww.. */
248 /* XXX we *could* optimise by falling out after doing num fds ... */
249 for (ci
= 0; ci
< pollfd_list
.maxindex
+ 1; ci
++)
253 if(((revents
= pollfd_list
.pollfds
[ci
].revents
) == 0) ||
254 (pollfd_list
.pollfds
[ci
].fd
) == -1)
256 fd
= pollfd_list
.pollfds
[ci
].fd
;
258 if(revents
& (POLLRDNORM
| POLLIN
| POLLHUP
| POLLERR
))
260 hdl
= F
->read_handler
;
261 F
->read_handler
= NULL
;
262 poll_update_pollfds(fd
, POLLRDNORM
, NULL
);
264 hdl(fd
, F
->read_data
);
266 if(revents
& (POLLWRNORM
| POLLOUT
| POLLHUP
| POLLERR
))
268 hdl
= F
->write_handler
;
269 F
->write_handler
= NULL
;
270 poll_update_pollfds(fd
, POLLWRNORM
, NULL
);
272 hdl(fd
, F
->write_data
);