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