]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/socketengine.h
8c74ce04427ccfba1ab6651821eb55e22fe9c483
[user/henk/code/inspircd.git] / include / socketengine.h
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  Inspire is copyright (C) 2002-2005 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 // Fill the engine with client file descriptors pending an action
18
19 #define epoll_fill      int i = epoll_wait(ep, event, 1, 5); \
20                         if (i > 0) \
21                         { \
22                                 log(DEBUG,"epoll_wait call: ep=%d, i=%d",ep,i); \
23                                 userrec* cu = fd_ref_table[event[0].data.fd];
24
25 #define kqueue_fill     ts.tv_sec = 0; \
26                         ts.tv_nsec = 1000L; \
27                         int i = kevent(kq, NULL, 0, &ke, 1, &ts); \
28                         if (i > 0) \
29                         { \
30                                 log(DEBUG,"kevent call: kq=%d, i=%d",kq,i); \
31                                 userrec* cu = fd_ref_table[ke.ident];
32
33 #define select_fill     tval.tv_sec = 0; \
34                         tval.tv_usec = 1000L; \
35                         selectResult2 = select(FD_SETSIZE, &sfd, NULL, NULL, &tval); \
36                         if ((selectResult2 > 0) && (xcount != clientlist.end())) \
37                         for (user_hash::iterator count2a = xcount; count2a != endingiter; count2a++) \
38                         { \
39                                 if (count2a == clientlist.end()) \
40                                         break; \
41                                 userrec* cu = count2a->second;
42
43 #ifdef USE_EPOLL
44 #define engine_fill epoll_fill
45 #endif
46 #ifdef USE_KQUEUE
47 #define engine_fill kqueue_fill
48 #endif
49 #ifdef USE_SELECT
50 #define engine_fill select_fill
51 #endif
52
53 // how to determine if a socket needs attention if further checks are needed
54
55 #define epoll_check    ((cu->fd != FD_MAGIC_NUMBER) && (cu->fd != -1))
56
57 #define kqueue_check   ((cu->fd != FD_MAGIC_NUMBER) && (cu->fd != -1))
58
59 #define select_check   ((cu->fd != FD_MAGIC_NUMBER) && (cu->fd != -1) && (FD_ISSET (cu->fd, &sfd)))
60
61 #ifdef USE_EPOLL
62 #define engine_check epoll_check
63 #endif
64 #ifdef USE_KQUEUE
65 #define engine_check kqueue_check
66 #endif
67 #ifdef USE_SELECT
68 #define engine_check select_check
69 #endif
70
71 // how to clean up an exiting client
72
73 #define epoll_cleanup                   log(DEBUG,"InspIRCd: Exited: %s",cu->nick); \
74                                         kill_link(cu,"Client exited"); \
75                                         log(DEBUG,"Bailing from client exit"); \
76                                         goto label;
77
78 #define kqueue_cleanup                  log(DEBUG,"InspIRCd: Exited: %s",cu->nick); \
79                                         kill_link(cu,"Client exited"); \
80                                         log(DEBUG,"Bailing from client exit"); \
81                                         goto label;
82
83 #define select_cleanup                  if (count2->second) \
84                                         { \
85                                                 log(DEBUG,"InspIRCd: Exited: %s",cu->nick); \
86                                                 kill_link(cu,"Client exited"); \
87                                                 log(DEBUG,"Bailing from client exit"); \
88                                                 goto label; \
89                                         }
90
91 #ifdef USE_EPOLL
92 #define engine_cleanup epoll_cleanup
93 #endif
94 #ifdef USE_KQUEUE
95 #define engine_cleanup kqueue_cleanup
96 #endif
97 #ifdef USE_SELECT
98 #define engine_cleanup select_cleanup
99 #endif
100
101
102 // how to scan the set for fd's requiring action
103
104 #define select_scanset          for (count = 0; count < boundPortCount; count++) \
105                                 { \
106                                         FD_SET (openSockfd[count], &selectFds); \
107                                 } \
108                                 tv.tv_usec = 30000L; \
109                                 selectResult = select(MAXSOCKS, &selectFds, NULL, NULL, &tv); \
110                                 if (selectResult > 0) \
111                                 { \
112                                         for (count = 0; count < boundPortCount; count++) \
113                                 { \
114                                                 if (FD_ISSET (openSockfd[count], &selectFds)) \
115                                                 {
116
117 #define kqueue_scanset          ts.tv_sec = 0; \
118                                 ts.tv_nsec = 30000L; \
119                                 i = kevent(lkq, NULL, 0, ke_list, 32, &ts); \
120                                 if (i > 0) for (j = 0; j < i; j++) \
121                                 { \
122                                         log(DEBUG,"kqueue: Listening socket event, i=%d, ke.ident=%d",i,ke_list[j].ident); \
123                                         for (count = 0; count < boundPortCount; count++) \
124                                         { \
125                                                 if ((unsigned)ke_list[j].ident == (unsigned)openSockfd[count]) \
126                                                 {
127
128 #define epoll_scanset           i = epoll_wait(lep, event, 32, EP_DELAY); \
129                                 if (i > 0) for (j = 0; j < i; j++) \
130                                 { \
131                                         log(DEBUG,"epoll: Listening socket event, i=%d,events[j].data.fd=%d",i,event[j].data.fd); \
132                                         for (count = 0; count < boundPortCount; count++) \
133                                         { \
134                                                 if ((unsigned)event[j].data.fd == (unsigned)openSockfd[count]) \
135                                                 {
136
137 #ifdef USE_EPOLL
138 #define engine_scanset epoll_scanset
139 #endif
140 #ifdef USE_KQUEUE
141 #define engine_scanset kqueue_scanset
142 #endif
143 #ifdef USE_SELECT
144 #define engine_scanset select_scanset
145 #endif
146
147 // how to populate the list with fds before asking for change notification
148
149 #define epoll_server_populate               i = epoll_wait(sep, event, 1, EP_DELAY); \
150                                         if (i > 0) \
151                                         { \
152                                                 log(DEBUG,"epoll: Listening server socket event, i=%d, event.data.fd=%d",i,event[0].data.fd); \
153                                                 for (int x = 0; x != SERVERportCount; x++) \
154                                                 { \
155                                                         if ((me[x]) && ((unsigned)event[0].data.fd == (unsigned)me[x]->fd)) \
156                                                         {
157 #define kqueue_server_populate              ts.tv_sec = 0; \
158                                         ts.tv_nsec = 30000L; \
159                                         i = kevent(skq, NULL, 0, &ke, 1, &ts); \
160                                         if (i > 0) \
161                                         { \
162                                                 log(DEBUG,"kqueue: Listening server socket event, i=%d, ke.ident=%d",i,ke.ident); \
163                                                 for (int x = 0; x != SERVERportCount; x++) \
164                                                 { \
165                                                         if ((me[x]) && ((unsigned)ke.ident == (unsigned)me[x]->fd)) \
166                                                         {
167
168 #define select_server_populate              FD_ZERO(&serverfds); \
169                                         for (int x = 0; x != SERVERportCount; x++) \
170                                         { \
171                                                 if (me[x]) \
172                                                         FD_SET(me[x]->fd, &serverfds); \
173                                         } \
174                                         tvs.tv_usec = 30000L; \
175                                         tvs.tv_sec = 0; \
176                                         int servresult = select(FD_SETSIZE, &serverfds, NULL, NULL, &tvs); \
177                                         if (servresult > 0) \
178                                         { \
179                                                 for (int x = 0; x != SERVERportCount; x++) \
180                                                 { \
181                                                         if ((me[x]) && (FD_ISSET (me[x]->fd, &serverfds))) \
182                                                         { 
183
184
185 #ifdef USE_EPOLL
186 #define engine_server_populate epoll_server_populate
187 #endif
188 #ifdef USE_KQUEUE
189 #define engine_server_populate kqueue_server_populate
190 #endif
191 #ifdef USE_SELECT
192 #define engine_server_populate select_server_populate
193 #endif
194
195 // a list of variables used specifically by this engine
196
197 #define kqueue_structs struct kevent ke; \
198         struct kevent ke_list[33]; \
199         struct timespec ts;
200
201 #define epoll_structs struct epoll_event event[33];
202
203 #define select_structs fd_set serverfds; \
204         fd_set sfd;
205
206 #ifdef USE_EPOLL
207 #define engine_structs epoll_structs
208 #endif
209 #ifdef USE_KQUEUE
210 #define engine_structs kqueue_structs
211 #endif
212 #ifdef USE_SELECT
213 #define engine_structs select_structs
214 #endif
215
216 // how to initialise the engine before using it
217
218 #define select_init     while(0);
219
220 #define kqueue_init     kq = kqueue(); \
221                         lkq = kqueue(); \
222                         skq = kqueue(); \
223                         if ((kq == -1) || (lkq == -1) || (skq == -1)) \
224                         { \
225                                 log(DEFAULT,"main: kqueue() failed!"); \
226                                 printf("ERROR: could not initialise kqueue event system. Shutting down.\n"); \
227                                 Exit(ERROR); \
228                         }
229
230 #define epoll_init      ep = epoll_create(MAXCLIENTS); \
231                         lep = epoll_create(32); \
232                         sep = epoll_create(128); \
233                         if ((ep == -1) || (lep == -1) || (sep == -1)) \
234                         { \
235                                 log(DEFAULT,"main: epoll_create() failed!"); \
236                                 printf("ERROR: could not initialise epoll event system. Shutting down.\n"); \
237                                 Exit(ERROR); \
238                         }
239
240
241 #ifdef USE_EPOLL
242 #define engine_init epoll_init
243 #endif
244 #ifdef USE_KQUEUE
245 #define engine_init kqueue_init
246 #endif
247 #ifdef USE_SELECT
248 #define engine_init select_init
249 #endif
250
251 // how to fill the engine with a list of server fd's
252
253 #define select_server_fill      log(DEFAULT,"Using standard select socket engine.");
254
255 #define epoll_server_fill        log(DEFAULT,"epoll socket engine is enabled. Filling listen list. boundPortcount=%d",boundPortCount); \
256                                 for (count = 0; count < boundPortCount; count++) \
257                                 { \
258                                         struct epoll_event ev; \
259                                         log(DEBUG,"epoll: Add listening socket to events, ep=%d socket=%d",lep,openSockfd[count]); \
260                                         ev.events = EPOLLIN | EPOLLET; \
261                                         ev.data.fd = openSockfd[count]; \
262                                         int i = epoll_ctl(lep, EPOLL_CTL_ADD, openSockfd[count], &ev); \
263                                         if (i < 0) \
264                                         { \
265                                                 log(DEFAULT,"main: add listen ports, epoll_ctl failed!"); \
266                                                 printf("ERROR: could not initialise listening sockets in epoll list. Shutting down.\n"); \
267                                                 Exit(ERROR); \
268                                         } \
269                                 } \
270                                 for (int t = 0; t != SERVERportCount; t++) \
271                                 { \
272                                         struct epoll_event ev; \
273                                         log(DEBUG,"epoll: Add listening server socket to events, ep=%d socket=%d",sep,me[t]->fd); \
274                                         ev.events = EPOLLIN | EPOLLET; \
275                                         ev.data.fd = me[t]->fd; \
276                                         int i = epoll_ctl(sep, EPOLL_CTL_ADD, me[t]->fd, &ev); \
277                                         if (i == -1) \
278                                         { \
279                                                 log(DEFAULT,"main: add server listen ports, epoll_ctl failed!"); \
280                                                 printf("ERROR: could not initialise server listening sockets in epoll list. Shutting down.\n"); \
281                                                 Exit(ERROR); \
282                                         } \
283                                 }
284
285 #define kqueue_server_fill        log(DEFAULT,"kqueue socket engine is enabled. Filling listen list."); \
286         for (count = 0; count < boundPortCount; count++) \
287         { \
288                 struct kevent ke; \
289                 log(DEBUG,"kqueue: Add listening socket to events, kq=%d socket=%d",lkq,openSockfd[count]); \
290                 EV_SET(&ke, openSockfd[count], EVFILT_READ, EV_ADD, 0, MaxConn, NULL); \
291                 int i = kevent(lkq, &ke, 1, 0, 0, NULL); \
292                 if (i == -1) \
293                 { \
294                         log(DEFAULT,"main: add listen ports to kqueue failed!"); \
295                         printf("ERROR: could not initialise listening sockets in kqueue. Shutting down.\n"); \
296                         Exit(ERROR); \
297                 } \
298         } \
299         for (int t = 0; t != SERVERportCount; t++) \
300         { \
301                 struct kevent ke; \
302                 if (me[t]) \
303                 { \
304                         log(DEBUG,"kqueue: Add listening SERVER socket to events, kq=%d socket=%d",skq,me[t]->fd); \
305                         EV_SET(&ke, me[t]->fd, EVFILT_READ, EV_ADD, 0, MaxConn, NULL); \
306                         int i = kevent(skq, &ke, 1, 0, 0, NULL); \
307                         if (i == -1) \
308                         { \
309                                 log(DEFAULT,"main: add server listen ports to kqueue failed!"); \
310                                 printf("ERROR: could not initialise listening server sockets in kqueue. Shutting down.\n"); \
311                                 Exit(ERROR); \
312                         } \
313                 } \
314         }
315
316 #ifdef USE_EPOLL
317 #define engine_server_fill epoll_server_fill
318 #endif
319 #ifdef USE_KQUEUE
320 #define engine_server_fill kqueue_server_fill
321 #endif
322 #ifdef USE_SELECT
323 #define engine_server_fill select_server_fill
324 #endif
325
326 // how to delete a client fd from the engine
327
328 #define kqueue_delete_fd        struct kevent ke; \
329                                 EV_SET(&ke, user->fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); \
330                                 int i = kevent(kq, &ke, 1, 0, 0, NULL); \
331                                 if (i == -1) \
332                                 { \
333                                         log(DEBUG,"kqueue: Failed to remove user from queue!"); \
334                                 }
335
336 #define epoll_delete_fd         struct epoll_event ev; \
337                                 ev.events = EPOLLIN | EPOLLET; \
338                                 ev.data.fd = user->fd; \
339                                 int i = epoll_ctl(ep, EPOLL_CTL_DEL, user->fd, &ev); \
340                                 if (i < 0) \
341                                 { \
342                                         log(DEBUG,"epoll: List deletion failure!"); \
343                                 }
344
345 #define select_delete_fd        while(0);
346
347
348 #ifdef USE_EPOLL
349 #define engine_delete_fd epoll_delete_fd
350 #endif
351 #ifdef USE_KQUEUE
352 #define engine_delete_fd kqueue_delete_fd
353 #endif
354 #ifdef USE_SELECT
355 #define engine_delete_fd select_delete_fd
356 #endif
357
358 // how to add a client fd to the engine
359
360 #define select_add_fd           while(0);
361
362 #define epoll_add_fd            struct epoll_event ev; \
363                                 log(DEBUG,"epoll: Adduser to events, ep=%d socket=%d",ep,socket); \
364                                 ev.events = EPOLLIN | EPOLLET; \
365                                 ev.data.fd = socket; \
366                                 int i = epoll_ctl(ep, EPOLL_CTL_ADD, socket, &ev); \
367                                 if (i < 0) \
368                                 { \
369                                         log(DEBUG,"epoll: List insertion failure!"); \
370                                 }
371
372 #define kqueue_add_fd           struct kevent ke; \
373                                 log(DEBUG,"kqueue: Add user to events, kq=%d socket=%d",kq,socket);\
374                                 EV_SET(&ke, socket, EVFILT_READ, EV_ADD, 0, 0, NULL); \
375                                 int i = kevent(kq, &ke, 1, 0, 0, NULL); \
376                                 if (i == -1) \
377                                 { \
378                                         log(DEBUG,"kqueue: List insertion failure!"); \
379                                 }
380
381 #ifdef USE_EPOLL
382 #define engine_add_fd epoll_add_fd
383 #endif
384 #ifdef USE_KQUEUE
385 #define engine_add_fd kqueue_add_fd
386 #endif
387 #ifdef USE_SELECT
388 #define engine_add_fd select_add_fd
389 #endif
390
391 // what is this engine called?
392
393 #ifdef USE_KQUEUE
394 #define engine_name "kqueue"
395 #endif
396 #ifdef USE_SELECT
397 #define engine_name "select"
398 #endif
399 #ifdef USE_EPOLL
400 #define engine_name "epoll"
401 #endif
402