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