/[svn]/ircd-hybrid/trunk/src/s_bsd_epoll.c
ViewVC logotype

Contents of /ircd-hybrid/trunk/src/s_bsd_epoll.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2725 - (show annotations)
Sun Dec 29 13:01:00 2013 UTC (8 years, 11 months ago) by michael
File MIME type: text/x-chdr
File size: 6051 byte(s)
- Fixed bug where ircd didn't timeout SSL connections that haven't
  finished the SSL handshake. Reported by Adam.

1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * s_bsd_epoll.c: Linux epoll() compatible network routines.
4 *
5 * Copyright (C) 2002-2005 Hybrid Development Team
6 * Based also on work of Adrian Chadd, Aaron Sethman and others.
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$
24 */
25
26 #include "stdinc.h"
27 #if USE_IOPOLL_MECHANISM == __IOPOLL_MECHANISM_EPOLL
28 #include "fdlist.h"
29 #include "ircd.h"
30 #include "memory.h"
31 #include "s_bsd.h"
32 #include "log.h"
33 #include <sys/epoll.h>
34 #include <sys/syscall.h>
35
36 static fde_t efd;
37
38 /* Thanks to ircu for the following ifdefs. */
39
40 /* The GNU C library may have a valid header but stub implementations
41 * of the epoll system calls. If so, provide our own. */
42 #if defined(__stub_epoll_create) || defined(__stub___epoll_create) || defined(EPOLL_NEED_BODY)
43
44 /* Oh, did we mention that some glibc releases do not even define the
45 * syscall numbers? */
46 #if !defined(__NR_epoll_create)
47 #if defined(__ia64__)
48 #define __NR_epoll_create 1243
49 #define __NR_epoll_ctl 1244
50 #define __NR_epoll_wait 1245
51 #elif defined(__x86_64__)
52 #define __NR_epoll_create 214
53 #define __NR_epoll_ctl 233
54 #define __NR_epoll_wait 232
55 #elif defined(__sparc64__) || defined(__sparc__)
56 #define __NR_epoll_create 193
57 #define __NR_epoll_ctl 194
58 #define __NR_epoll_wait 195
59 #elif defined(__s390__) || defined(__m68k__)
60 #define __NR_epoll_create 249
61 #define __NR_epoll_ctl 250
62 #define __NR_epoll_wait 251
63 #elif defined(__ppc64__) || defined(__ppc__)
64 #define __NR_epoll_create 236
65 #define __NR_epoll_ctl 237
66 #define __NR_epoll_wait 238
67 #elif defined(__parisc__) || defined(__arm26__) || defined(__arm__)
68 #define __NR_epoll_create 224
69 #define __NR_epoll_ctl 225
70 #define __NR_epoll_wait 226
71 #elif defined(__alpha__)
72 #define __NR_epoll_create 407
73 #define __NR_epoll_ctl 408
74 #define __NR_epoll_wait 409
75 #elif defined(__sh64__)
76 #define __NR_epoll_create 282
77 #define __NR_epoll_ctl 283
78 #define __NR_epoll_wait 284
79 #elif defined(__i386__) || defined(__sh__) || defined(__m32r__) || defined(__h8300__) || defined(__frv__)
80 #define __NR_epoll_create 254
81 #define __NR_epoll_ctl 255
82 #define __NR_epoll_wait 256
83 #else /* cpu types */
84 #error No system call numbers defined for epoll family.
85 #endif /* cpu types */
86 #endif /* !defined(__NR_epoll_create) */
87
88 _syscall1(int, epoll_create, int, size)
89 _syscall4(int, epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event *, event)
90 _syscall4(int, epoll_wait, int, epfd, struct epoll_event *, pevents, int, maxevents, int, timeout)
91
92 #endif /* epoll_create defined as stub */
93
94 /*
95 * init_netio
96 *
97 * This is a needed exported function which will be called to initialise
98 * the network loop code.
99 */
100 void
101 init_netio(void)
102 {
103 int fd;
104
105 if ((fd = epoll_create(hard_fdlimit)) < 0)
106 {
107 ilog(LOG_TYPE_IRCD, "init_netio: Couldn't open epoll fd - %d: %s",
108 errno, strerror(errno));
109 exit(115); /* Whee! */
110 }
111
112 fd_open(&efd, fd, 0, "epoll file descriptor");
113 }
114
115 /*
116 * comm_setselect
117 *
118 * This is a needed exported function which will be called to register
119 * and deregister interest in a pending IO state for a given FD.
120 */
121 void
122 comm_setselect(fde_t *F, unsigned int type, PF *handler,
123 void *client_data, time_t timeout)
124 {
125 int new_events, op;
126 struct epoll_event ep_event = { 0, { 0 } };
127
128 if ((type & COMM_SELECT_READ))
129 {
130 F->read_handler = handler;
131 F->read_data = client_data;
132 }
133
134 if ((type & COMM_SELECT_WRITE))
135 {
136 F->write_handler = handler;
137 F->write_data = client_data;
138 }
139
140 new_events = (F->read_handler ? EPOLLIN : 0) |
141 (F->write_handler ? EPOLLOUT : 0);
142
143 if (timeout != 0)
144 {
145 F->timeout = CurrentTime + (timeout / 1000);
146 F->timeout_handler = handler;
147 F->timeout_data = client_data;
148 }
149
150 if (new_events != F->evcache)
151 {
152 if (new_events == 0)
153 op = EPOLL_CTL_DEL;
154 else if (F->evcache == 0)
155 op = EPOLL_CTL_ADD;
156 else
157 op = EPOLL_CTL_MOD;
158
159 ep_event.events = F->evcache = new_events;
160 ep_event.data.fd = F->fd;
161
162 if (epoll_ctl(efd.fd, op, F->fd, &ep_event) != 0)
163 {
164 ilog(LOG_TYPE_IRCD, "comm_setselect: epoll_ctl() failed: %s", strerror(errno));
165 abort();
166 }
167 }
168 }
169
170 /*
171 * comm_select()
172 *
173 * Called to do the new-style IO, courtesy of of squid (like most of this
174 * new IO code). This routine handles the stuff we've hidden in
175 * comm_setselect and fd_table[] and calls callbacks for IO ready
176 * events.
177 */
178 void
179 comm_select(void)
180 {
181 struct epoll_event ep_fdlist[128];
182 int num, i;
183 PF *hdl;
184 fde_t *F;
185
186 num = epoll_wait(efd.fd, ep_fdlist, 128, SELECT_DELAY);
187
188 set_time();
189
190 if (num < 0)
191 {
192 #ifdef HAVE_USLEEP
193 usleep(50000); /* avoid 99% CPU in comm_select */
194 #endif
195 return;
196 }
197
198 for (i = 0; i < num; i++)
199 {
200 F = lookup_fd(ep_fdlist[i].data.fd);
201 if (F == NULL || !F->flags.open)
202 continue;
203
204 if ((ep_fdlist[i].events & (EPOLLIN | EPOLLHUP | EPOLLERR)))
205 {
206 if ((hdl = F->read_handler) != NULL)
207 {
208 F->read_handler = NULL;
209 hdl(F, F->read_data);
210 if (!F->flags.open)
211 continue;
212 }
213 }
214
215 if ((ep_fdlist[i].events & (EPOLLOUT | EPOLLHUP | EPOLLERR)))
216 {
217 if ((hdl = F->write_handler) != NULL)
218 {
219 F->write_handler = NULL;
220 hdl(F, F->write_data);
221 if (!F->flags.open)
222 continue;
223 }
224 }
225
226 comm_setselect(F, 0, NULL, NULL, 0);
227 }
228 }
229 #endif

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28