]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/socketengine.cpp
49624481ffe76bb90d853eaf339d6a7dd6beca4a
[user/henk/code/inspircd.git] / src / socketengine.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
6  * See: http://wiki.inspircd.org/Credits
7  *
8  * This program is free but copyrighted software; see
9  *          the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 /* $Core */
15
16 /*********        DEFAULTS       **********/
17
18 /* $ExtraSources: socketengines/socketengine_select.cpp */
19 /* $ExtraObjects: socketengine_select.o */
20
21 /* $If: USE_POLL */
22 /* $ExtraSources: socketengines/socketengine_poll.cpp */
23 /* $ExtraObjects: socketengine_poll.o */
24 /* $EndIf */
25
26 /* $If: USE_KQUEUE */
27 /* $ExtraSources: socketengines/socketengine_kqueue.cpp */
28 /* $ExtraObjects: socketengine_kqueue.o */
29 /* $EndIf */
30
31 /* $If: USE_EPOLL */
32 /* $ExtraSources: socketengines/socketengine_epoll.cpp */
33 /* $ExtraObjects: socketengine_epoll.o */
34 /* $EndIf */
35
36 /* $If: USE_PORTS */
37 /* $ExtraSources: socketengines/socketengine_ports.cpp */
38 /* $ExtraObjects: socketengine_ports.o */
39 /* $EndIf */
40
41 #include "inspircd.h"
42 #include "socketengine.h"
43
44 EventHandler::EventHandler()
45 {
46         fd = -1;
47 }
48
49 void EventHandler::SetFd(int FD)
50 {
51         this->fd = FD;
52 }
53
54 SocketEngine::SocketEngine()
55 {
56         TotalEvents = WriteEvents = ReadEvents = ErrorEvents = 0;
57         lastempty = ServerInstance->Time();
58         indata = outdata = 0;
59 }
60
61 SocketEngine::~SocketEngine()
62 {
63 }
64
65 void SocketEngine::SetEventMask(EventHandler* eh, int mask)
66 {
67         eh->event_mask = mask;
68 }
69
70 void SocketEngine::ChangeEventMask(EventHandler* eh, int change)
71 {
72         int old_m = eh->event_mask;
73         int new_m = old_m;
74
75         // if we are changing read/write type, remove the previously set bit
76         if (change & FD_WANT_READ_MASK)
77                 new_m &= ~FD_WANT_READ_MASK;
78         if (change & FD_WANT_WRITE_MASK)
79                 new_m &= ~FD_WANT_WRITE_MASK;
80         
81         // if adding a trial read/write, insert it into the set
82         if (change & FD_TRIAL_NOTE_MASK && !(old_m & FD_TRIAL_NOTE_MASK))
83                 trials.insert(eh->GetFd());
84
85         new_m |= change;
86         if (new_m == old_m)
87                 return;
88
89         eh->event_mask = new_m;
90         OnSetEvent(eh, old_m, new_m);
91 }
92
93 void SocketEngine::DispatchTrialWrites()
94 {
95         std::vector<int> working_list;
96         working_list.reserve(trials.size());
97         working_list.assign(trials.begin(), trials.end());
98         trials.clear();
99         for(unsigned int i=0; i < working_list.size(); i++)
100         {
101                 int fd = working_list[i];
102                 EventHandler* eh = GetRef(fd);
103                 if (!eh)
104                         continue;
105                 int mask = eh->event_mask;
106                 eh->event_mask &= ~(FD_ADD_TRIAL_READ | FD_ADD_TRIAL_WRITE);
107                 if ((mask & (FD_ADD_TRIAL_READ | FD_READ_WILL_BLOCK)) == FD_ADD_TRIAL_READ)
108                         eh->HandleEvent(EVENT_READ, 0);
109                 if ((mask & (FD_ADD_TRIAL_WRITE | FD_WRITE_WILL_BLOCK)) == FD_ADD_TRIAL_WRITE)
110                         eh->HandleEvent(EVENT_WRITE, 0);
111         }
112 }
113
114 bool SocketEngine::HasFd(int fd)
115 {
116         if ((fd < 0) || (fd > GetMaxFds()))
117                 return false;
118         return ref[fd];
119 }
120
121 EventHandler* SocketEngine::GetRef(int fd)
122 {
123         if ((fd < 0) || (fd > GetMaxFds()))
124                 return 0;
125         return ref[fd];
126 }
127
128 bool SocketEngine::BoundsCheckFd(EventHandler* eh)
129 {
130         if (!eh)
131                 return false;
132         if ((eh->GetFd() < 0) || (eh->GetFd() > GetMaxFds()))
133                 return false;
134         return true;
135 }
136
137
138 int SocketEngine::Accept(EventHandler* fd, sockaddr *addr, socklen_t *addrlen)
139 {
140         return accept(fd->GetFd(), addr, addrlen);
141 }
142
143 int SocketEngine::Close(EventHandler* fd)
144 {
145 #ifdef WINDOWS
146         return closesocket(fd->GetFd());
147 #else
148         return close(fd->GetFd());
149 #endif
150 }
151
152 int SocketEngine::Close(int fd)
153 {
154 #ifdef WINDOWS
155         return closesocket(fd);
156 #else
157         return close(fd);
158 #endif
159 }
160
161 int SocketEngine::Blocking(int fd)
162 {
163 #ifdef WINDOWS
164         unsigned long opt = 0;
165         return ioctlsocket(fd, FIONBIO, &opt);
166 #else
167         int flags = fcntl(fd, F_GETFL, 0);
168         return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
169 #endif
170 }
171
172 int SocketEngine::NonBlocking(int fd)
173 {
174 #ifdef WINDOWS
175         unsigned long opt = 1;
176         return ioctlsocket(fd, FIONBIO, &opt);
177 #else
178         int flags = fcntl(fd, F_GETFL, 0);
179         return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
180 #endif
181 }
182
183 int SocketEngine::GetSockName(EventHandler* fd, sockaddr *name, socklen_t* namelen)
184 {
185         return getsockname(fd->GetFd(), name, namelen);
186 }
187
188 int SocketEngine::RecvFrom(EventHandler* fd, void *buf, size_t len, int flags, sockaddr *from, socklen_t *fromlen)
189 {
190         this->UpdateStats(len, 0);
191         return recvfrom(fd->GetFd(), buf, len, flags, from, fromlen);
192 }
193
194 int SocketEngine::Send(EventHandler* fd, const void *buf, size_t len, int flags)
195 {
196         this->UpdateStats(0, len);
197         return send(fd->GetFd(), buf, len, flags);
198 }
199
200 int SocketEngine::Recv(EventHandler* fd, void *buf, size_t len, int flags)
201 {
202         this->UpdateStats(len, 0);
203         return recv(fd->GetFd(), buf, len, flags);
204 }
205
206 int SocketEngine::SendTo(EventHandler* fd, const void *buf, size_t len, int flags, const sockaddr *to, socklen_t tolen)
207 {
208         this->UpdateStats(0, len);
209         return sendto(fd->GetFd(), buf, len, flags, to, tolen);
210 }
211
212 int SocketEngine::Connect(EventHandler* fd, const sockaddr *serv_addr, socklen_t addrlen)
213 {
214         return connect(fd->GetFd(), serv_addr, addrlen);
215 }
216
217 int SocketEngine::Shutdown(EventHandler* fd, int how)
218 {
219         return shutdown(fd->GetFd(), how);
220 }
221
222 int SocketEngine::Bind(int fd, const sockaddr *my_addr, socklen_t addrlen)
223 {
224         return bind(fd, my_addr, addrlen);
225 }
226
227 int SocketEngine::Listen(int sockfd, int backlog)
228 {
229         return listen(sockfd, backlog);
230 }
231
232 int SocketEngine::Shutdown(int fd, int how)
233 {
234         return shutdown(fd, how);
235 }
236
237 void SocketEngine::RecoverFromFork()
238 {
239 }
240
241 void SocketEngine::UpdateStats(size_t len_in, size_t len_out)
242 {
243         if (lastempty != ServerInstance->Time())
244         {
245                 lastempty = ServerInstance->Time();
246                 indata = outdata = 0;
247         }
248         indata += len_in;
249         outdata += len_out;
250 }
251
252 void SocketEngine::GetStats(float &kbitpersec_in, float &kbitpersec_out, float &kbitpersec_total)
253 {
254         UpdateStats(0, 0); /* Forces emptying of the values if its been more than a second */
255         float in_kbit = indata * 8;
256         float out_kbit = outdata * 8;
257         kbitpersec_total = ((in_kbit + out_kbit) / 1024);
258         kbitpersec_in = in_kbit / 1024;
259         kbitpersec_out = out_kbit / 1024;
260 }