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