InspIRCd  4.0
socketengine.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  * Copyright (C) 2013-2016 Attila Molnar <[email protected]>
5  * Copyright (C) 2013-2014 Adam <[email protected]>
6  * Copyright (C) 2012-2013, 2017-2020 Sadie Powell <[email protected]>
7  * Copyright (C) 2012 Robby <[email protected]>
8  * Copyright (C) 2009-2010 Daniel De Graaf <[email protected]>
9  * Copyright (C) 2009 Uli Schlachter <[email protected]>
10  * Copyright (C) 2007-2008, 2017 Robin Burchell <[email protected]>
11  * Copyright (C) 2007 Dennis Friis <[email protected]>
12  * Copyright (C) 2005-2008 Craig Edwards <[email protected]>
13  *
14  * This file is part of InspIRCd. InspIRCd is free software: you can
15  * redistribute it and/or modify it under the terms of the GNU General Public
16  * License as published by the Free Software Foundation, version 2.
17  *
18  * This program is distributed in the hope that it will be useful, but WITHOUT
19  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
21  * details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program. If not, see <http://www.gnu.org/licenses/>.
25  */
26 
27 
28 #pragma once
29 
30 #include <string>
31 #include "socket.h"
32 #include "base.h"
33 
34 #ifndef _WIN32
35 #include <sys/uio.h>
36 #endif
37 
38 #ifndef IOV_MAX
39 #define IOV_MAX 1024
40 #endif
41 
45 enum EventMask
46 {
49  FD_WANT_NO_READ = 0x1,
52  FD_WANT_POLL_READ = 0x2,
59  FD_WANT_FAST_READ = 0x4,
66  FD_WANT_EDGE_READ = 0x8,
67 
69  FD_WANT_READ_MASK = 0x0F,
70 
73  FD_WANT_NO_WRITE = 0x10,
81  FD_WANT_POLL_WRITE = 0x20,
95  FD_WANT_FAST_WRITE = 0x40,
101  FD_WANT_EDGE_WRITE = 0x80,
105  FD_WANT_SINGLE_WRITE = 0x100,
106 
108  FD_WANT_WRITE_MASK = 0x1F0,
109 
114  FD_ADD_TRIAL_READ = 0x1000,
118  FD_READ_WILL_BLOCK = 0x2000,
119 
128  FD_ADD_TRIAL_WRITE = 0x4000,
132  FD_WRITE_WILL_BLOCK = 0x8000,
133 
135  FD_TRIAL_NOTE_MASK = 0x5000
136 };
137 
153 class CoreExport EventHandler : public Cullable
154 {
155  private:
157  int event_mask;
158 
159  void SetEventMask(int mask) { event_mask = mask; }
160 
161  protected:
168  int fd;
169 
170  public:
174  inline int GetFd() const { return fd; }
175 
177  inline bool HasFd() const { return fd >= 0; }
178 
179  inline int GetEventMask() const { return event_mask; }
180 
186  void SetFd(int FD);
187 
190  EventHandler();
191 
194  virtual void OnEventHandlerRead() = 0;
195 
199  virtual void OnEventHandlerWrite();
200 
205  virtual void OnEventHandlerError(int errornum);
206 
207  friend class SocketEngine;
208 };
209 
218 class CoreExport SocketEngine
219 {
220  public:
224  {
225  mutable size_t indata = 0;
226  mutable size_t outdata = 0;
227  mutable time_t lastempty = 0;
228 
231  void CheckFlush() const;
232 
233  public:
239  void UpdateReadCounters(ssize_t len_in);
240 
246  void UpdateWriteCounters(ssize_t len_out);
247 
253  void CoreExport GetBandwidth(float& kbitpersec_in, float& kbitpersec_out, float& kbitpersec_total) const;
254 
255  unsigned long TotalEvents = 0;
256  unsigned long ReadEvents = 0;
257  unsigned long WriteEvents = 0;
258  unsigned long ErrorEvents = 0;
259  };
260 
261  private:
264  static std::vector<EventHandler*> ref;
265 
267  static size_t CurrentSetSize;
268 
270  static size_t MaxSetSize;
271 
274  static std::set<int> trials;
275 
278  static Statistics stats;
279 
281  static void LookupMaxFds();
282 
284  [[noreturn]]
285  static void InitError();
286 
287  static void OnSetEvent(EventHandler* eh, int old_mask, int new_mask);
288 
291  static bool AddFdRef(EventHandler* eh);
292 
293  static void DelFdRef(EventHandler* eh);
294 
295  template <typename T>
296  static void ResizeDouble(std::vector<T>& vect)
297  {
298  if (SocketEngine::CurrentSetSize > vect.size())
299  vect.resize(SocketEngine::CurrentSetSize * 2);
300  }
301 
302 public:
303 #ifndef _WIN32
304  typedef iovec IOVector;
305 #else
306  typedef WindowsIOVec IOVector;
307 #endif
308 
317  static void Init();
318 
323  static void Deinit();
324 
332  static bool AddFd(EventHandler* eh, int event_mask);
333 
345  static void ChangeEventMask(EventHandler* eh, int event_mask);
346 
352  static size_t GetMaxFds() { return MaxSetSize; }
353 
357  static size_t GetUsedFds() { return CurrentSetSize; }
358 
367  static void DelFd(EventHandler* eh);
368 
374  static bool HasFd(int fd);
375 
381  static EventHandler* GetRef(int fd);
382 
390  static int DispatchEvents();
391 
395  static void DispatchTrialWrites();
396 
400  static bool BoundsCheckFd(EventHandler* eh);
401 
409  static int Accept(EventHandler* fd, sockaddr *addr, socklen_t *addrlen);
410 
415  static int Close(EventHandler* eh);
416 
422  static int Close(int fd);
423 
432  static ssize_t Send(EventHandler* fd, const void *buf, size_t len, int flags);
433 
442  static ssize_t WriteV(EventHandler* fd, const IOVector* iov, int count);
443 
444 #ifdef _WIN32
452  static int WriteV(EventHandler* fd, const iovec* iov, int count);
453 #endif
454 
463  static ssize_t Recv(EventHandler* fd, void *buf, size_t len, int flags);
464 
475  static ssize_t RecvFrom(EventHandler* fd, void *buf, size_t len, int flags, sockaddr *from, socklen_t *fromlen);
476 
486  static ssize_t SendTo(EventHandler* fd, const void* buf, size_t len, int flags, const irc::sockets::sockaddrs& address);
487 
494  static int Connect(EventHandler* fd, const irc::sockets::sockaddrs& address);
495 
500  static int Blocking(int fd);
501 
506  static int NonBlocking(int fd);
507 
514  static int Shutdown(EventHandler* fd, int how);
515 
520  static int Shutdown(int fd, int how);
521 
526  static int Bind(int fd, const irc::sockets::sockaddrs& addr);
527 
532  static int Listen(int sockfd, int backlog);
533 
536  static void SetReuse(int sockfd);
537 
545  static void RecoverFromFork();
546 
549  static const Statistics& GetStats() { return stats; }
550 
554  static bool IgnoreError();
555 
558  static std::string LastError();
559 
562  static std::string GetError(int errnum);
563 };
564 
566 {
567  if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
568  return true;
569 
570 #ifdef _WIN32
571  if (WSAGetLastError() == WSAEWOULDBLOCK)
572  return true;
573 #endif
574 
575  return false;
576 }
Definition: cull.h:30
Definition: socketengine.h:154
bool HasFd() const
Definition: socketengine.h:177
int GetFd() const
Definition: socketengine.h:174
virtual void OnEventHandlerRead()=0
int fd
Definition: socketengine.h:168
Definition: socketengine.h:224
Definition: socketengine.h:219
static size_t GetMaxFds()
Definition: socketengine.h:352
static bool IgnoreError()
Definition: socketengine.h:565
static size_t GetUsedFds()
Definition: socketengine.h:357
static const Statistics & GetStats()
Definition: socketengine.h:549
Definition: inspircd_win32wrapper.h:177
Definition: inspircd_win32wrapper.h:170
Definition: socket.h:63