]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/socketengine.cpp
d482fd6d67a7bd05b7d2412d3463a426e5191329
[user/henk/code/inspircd.git] / src / socketengine.cpp
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 #include "inspircd_config.h"
18 #include "globals.h"
19 #include "inspircd.h"
20 #ifdef USE_EPOLL
21 #include <sys/epoll.h>
22 #define EP_DELAY 5
23 #endif
24 #ifdef USE_KQUEUE
25 #include <sys/types.h>
26 #include <sys/event.h>
27 #include <sys/time.h>
28 #endif
29 #include <vector>
30 #include <string>
31 #include "socketengine.h"
32
33 char ref[65535];
34
35 SocketEngine::SocketEngine()
36 {
37         log(DEBUG,"SocketEngine::SocketEngine()");
38 #ifdef USE_EPOLL
39         EngineHandle = epoll_create(65535);
40 #endif
41 #ifdef USE_KQUEUE
42         EngineHandle = kqueue();
43 #endif
44 }
45
46 SocketEngine::~SocketEngine()
47 {
48         log(DEBUG,"SocketEngine::~SocketEngine()");
49 #ifdef USE_EPOLL
50         close(EngineHandle);
51 #endif
52 #ifdef USE_KQUEUE
53         close(EngineHandle);
54 #endif
55 }
56
57 char SocketEngine::GetType(int fd)
58 {
59         if ((fd < 0) || (fd > 65535))
60                 return X_EMPTY_SLOT;
61         /* Mask off the top bit used for 'read/write' state */
62         return (ref[fd] & ~0x80);
63 }
64
65 bool SocketEngine::AddFd(int fd, bool readable, char type)
66 {
67         if ((fd < 0) || (fd > 65535))
68                 return false;
69         this->fds.push_back(fd);
70         ref[fd] = type;
71         if (readable)
72         {
73                 log(DEBUG,"Set readbit");
74                 ref[fd] |= X_READBIT;
75         }
76         log(DEBUG,"Add socket %d",fd);
77 #ifdef USE_EPOLL
78         struct epoll_event ev;
79         log(DEBUG,"epoll: Add socket to events, ep=%d socket=%d",EngineHandle,fd);
80         readable ? ev.events = EPOLLIN | EPOLLET : ev.events = EPOLLOUT | EPOLLET;
81         ev.data.fd = fd;
82         int i = epoll_ctl(EngineHandle, EPOLL_CTL_ADD, fd, &ev);
83         if (i < 0)
84         {
85                 log(DEBUG,"epoll: List insertion failure!");
86                 return false;
87         }
88 #endif
89 #ifdef USE_KQUEUE
90         struct kevent ke;
91         log(DEBUG,"kqueue: Add socket to events, kq=%d socket=%d",EngineHandle,fd);
92         EV_SET(&ke, fd, readable ? EVFILT_READ : EVFILT_WRITE, EV_ADD, 0, 0, NULL);
93         int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
94         if (i == -1)
95         {
96                 log(DEBUG,"kqueue: List insertion failure!");
97                 return false;
98         }
99 #endif
100 return true;
101 }
102
103 bool SocketEngine::DelFd(int fd)
104 {
105         log(DEBUG,"SocketEngine::DelFd(%d)",fd);
106
107         if ((fd < 0) || (fd > 65535))
108                 return false;
109
110         bool found = false;
111         for (std::vector<int>::iterator i = fds.begin(); i != fds.end(); i++)
112         {
113                 if (*i == fd)
114                 {
115                         fds.erase(i);
116                         log(DEBUG,"Deleted fd %d",fd);
117                         found = true;
118                         break;
119                 }
120         }
121 #ifdef USE_KQUEUE
122         struct kevent ke;
123         EV_SET(&ke, fd, ref[fd] && X_READBIT ? EVFILT_READ : EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
124         int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
125         if (i == -1)
126         {
127                 log(DEBUG,"kqueue: Failed to remove socket from queue!");
128                 return false;
129         }
130 #endif
131 #ifdef USE_EPOLL
132         struct epoll_event ev;
133         ref[fd] && X_READBIT ? ev.events = EPOLLIN | EPOLLET : ev.events = EPOLLOUT | EPOLLET;
134         ev.data.fd = fd;
135         int i = epoll_ctl(EngineHandle, EPOLL_CTL_DEL, fd, &ev);
136         if (i < 0)
137         {
138                 log(DEBUG,"epoll: List deletion failure!");
139                 return false;
140         }
141 #endif
142         ref[fd] = 0;
143         return found;
144 }
145
146 bool SocketEngine::Wait(std::vector<int> &fdlist)
147 {
148         fdlist.clear();
149 #ifdef USE_SELECT
150         FD_ZERO(&wfdset);
151         FD_ZERO(&rfdset);
152         timeval tval;
153         int sresult;
154         for (unsigned int a = 0; a < fds.size(); a++)
155         {
156                 if (ref[fds[a]] & X_READBIT)
157                 {
158                         FD_SET (fds[a], &rfdset);
159                 }
160                 else
161                 {
162                         FD_SET (fds[a], &wfdset);
163                 }
164                 
165         }
166         tval.tv_sec = 0;
167         tval.tv_usec = 10000L;
168         sresult = select(FD_SETSIZE, &rfdset, &wfdset, NULL, &tval);
169         if (sresult > 0)
170         {
171                 for (unsigned int a = 0; a < fds.size(); a++)
172                 {
173                         if ((FD_ISSET (fds[a], &rfdset)) || (FD_ISSET (fds[a], &wfdset)))
174                         {
175                                 log(DEBUG,"...Adding active %d",fds[a]);
176                                 fdlist.push_back(fds[a]);
177                         }
178                 }
179         }
180 #endif
181 #ifdef USE_KQUEUE
182         ts.tv_nsec = 10000L;
183         ts.tv_sec = 0;
184         int i = kevent(EngineHandle, NULL, 0, &ke_list[0], 65535, &ts);
185         for (int j = 0; j < i; j++)
186                 fdlist.push_back(ke_list[j].ident);
187 #endif
188 #ifdef USE_EPOLL
189         int i = epoll_wait(EngineHandle, events, 65535, 100);
190         for (int j = 0; j < i; j++)
191                 fdlist.push_back(events[j].data.fd);
192 #endif
193         return true;
194 }
195
196 std::string SocketEngine::GetName()
197 {
198 #ifdef USE_SELECT
199         return "select";
200 #endif
201 #ifdef USE_KQUEUE
202         return "kqueue";
203 #endif
204 #ifdef USE_EPOLL
205         return "epoll";
206 #endif
207         return "misconfigured";
208 }