]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/socketengine.cpp
X_MODULE -> X_ESTAB_MODULE
[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         /* Mask off the top bit used for 'read/write' state */
44         return (ref[fd] & 0x7F);
45 }
46
47 bool SocketEngine::AddFd(int fd, bool readable, char type)
48 {
49         this->fds.push_back(fd);
50         if (readable)
51                 ref[fd] |= X_READBIT;
52 #ifdef USE_EPOLL
53         struct epoll_event ev;
54         log(DEBUG,"epoll: Add socket to events, ep=%d socket=%d",EngineHandle,fd);
55         readable ? ev.events = EPOLLIN | EPOLLET : ev.events = EPOLLOUT | EPOLLET;
56         ev.data.fd = fd;
57         int i = epoll_ctl(EngineHandle, EPOLL_CTL_ADD, fd, &ev);
58         if (i < 0)
59         {
60                 log(DEBUG,"epoll: List insertion failure!");
61                 return false;
62         }
63 #endif
64 #ifdef USE_KQUEUE
65         struct kevent ke;
66         log(DEBUG,"kqueue: Add socket to events, kq=%d socket=%d",EngineHandle,fd);
67         EV_SET(&ke, fd, readable ? EVFILT_READ : EVFILT_WRITE, EV_ADD, 0, 0, NULL);
68         int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
69         if (i == -1)
70         {
71                 log(DEBUG,"kqueue: List insertion failure!");
72                 return false;
73         }
74 #endif
75 return true;
76 }
77
78 bool SocketEngine::DelFd(int fd)
79 {
80         log(DEBUG,"SocketEngine::DelFd(%d)",fd);
81         bool found = false;
82         for (std::vector<int>::iterator i = fds.begin(); i != fds.end(); i++)
83         {
84                 if (*i == fd)
85                 {
86                         fds.erase(i);
87                         found = true;
88                         break;
89                 }
90         }
91 #ifdef USE_KQUEUE
92         struct kevent ke;
93         EV_SET(&ke, fd, ref[fd] && X_READBIT ? EVFILT_READ : EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
94         int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
95         if (i == -1)
96         {
97                 log(DEBUG,"kqueue: Failed to remove socket from queue!");
98                 return false;
99         }
100 #endif
101 #ifdef USE_EPOLL
102         struct epoll_event ev;
103         ref[fd] && X_READBIT ? ev.events = EPOLLIN | EPOLLET : ev.events = EPOLLOUT | EPOLLET;
104         ev.data.fd = fd;
105         int i = epoll_ctl(EngineHandle, EPOLL_CTL_DEL, fd, &ev);
106         if (i < 0)
107         {
108                 log(DEBUG,"epoll: List deletion failure!");
109                 return false;
110         }
111 #endif
112         ref[fd] = 0;
113         return found;
114 }
115
116 bool SocketEngine::Wait(std::vector<int> &fdlist)
117 {
118         fdlist.clear();
119 #ifdef USE_SELECT
120         FD_ZERO(&wfdset);
121         FD_ZERO(&rfdset);
122         timeval tval;
123         int sresult;
124         for (unsigned int a = 0; a < fds.size(); a++)
125         {
126                 if (ref[fds[a]] && X_READBIT)
127                 {
128                         FD_SET (fds[a], &rfdset);
129                 }
130                 else
131                 {
132                         FD_SET (fds[a], &wfdset);
133                 }
134                 
135         }
136         tval.tv_sec = 0;
137         tval.tv_usec = 1000L;
138         sresult = select(FD_SETSIZE, &rfdset, &wfdset, NULL, &tval);
139         if (sresult > 0)
140         {
141                 for (unsigned int a = 0; a < fds.size(); a++)
142                 {
143                         if ((FD_ISSET (fds[a], &rfdset)) || (FD_ISSET (fds[a], &wfdset)))
144                                 fdlist.push_back(fds[a]);
145                 }
146         }
147 #endif
148 #ifdef USE_KQUEUE
149         ts.tv_nsec = 1000L;
150         ts.tv_sec = 0;
151         int i = kevent(EngineHandle, NULL, 0, &ke_list[0], 65535, &ts);
152         for (int j = 0; j < i; j++)
153                 fdlist.push_back(ke_list[j].ident);
154 #endif
155 #ifdef USE_EPOLL
156         int i = epoll_wait(EngineHandle, events, 65535, 1);
157         for (int j = 0; j < i; j++)
158                 fdlist.push_back(events[j].data.fd);
159 #endif
160         return true;
161 }
162
163 std::string SocketEngine::GetName()
164 {
165 #ifdef USE_SELECT
166         return "select";
167 #endif
168 #ifdef USE_KQUEUE
169         return "kqueue";
170 #endif
171 #ifdef USE_EPOLL
172         return "epoll";
173 #endif
174         return "misconfigured";
175 }