InspIRCd  3.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 classbase
154 {
155  private:
157  int event_mask;
158 
159  void SetEventMask(int mask) { event_mask = mask; }
160 
161  protected:
168  int fd;
169 
173  void SwapInternals(EventHandler& other);
174 
175  public:
179  inline int GetFd() const { return fd; }
180 
182  inline bool HasFd() const { return fd >= 0; }
183 
184  inline int GetEventMask() const { return event_mask; }
185 
191  void SetFd(int FD);
192 
195  EventHandler();
196 
199  virtual ~EventHandler() {}
200 
203  virtual void OnEventHandlerRead() = 0;
204 
208  virtual void OnEventHandlerWrite();
209 
214  virtual void OnEventHandlerError(int errornum);
215 
216  friend class SocketEngine;
217 };
218 
227 class CoreExport SocketEngine
228 {
229  public:
233  {
234  mutable size_t indata;
235  mutable size_t outdata;
236  mutable time_t lastempty;
237 
240  void CheckFlush() const;
241 
242  public:
246  Statistics() : lastempty(0), TotalEvents(0), ReadEvents(0), WriteEvents(0), ErrorEvents(0) { }
247 
253  void UpdateReadCounters(int len_in);
254 
260  void UpdateWriteCounters(int len_out);
261 
267  void CoreExport GetBandwidth(float& kbitpersec_in, float& kbitpersec_out, float& kbitpersec_total) const;
268 
269  unsigned long TotalEvents;
270  unsigned long ReadEvents;
271  unsigned long WriteEvents;
272  unsigned long ErrorEvents;
273  };
274 
275  private:
278  static std::vector<EventHandler*> ref;
279 
281  static size_t CurrentSetSize;
282 
284  static size_t MaxSetSize;
285 
288  static std::set<int> trials;
289 
292  static Statistics stats;
293 
295  static void LookupMaxFds();
296 
298  static void InitError();
299 
300  static void OnSetEvent(EventHandler* eh, int old_mask, int new_mask);
301 
304  static bool AddFdRef(EventHandler* eh);
305 
306  static void DelFdRef(EventHandler* eh);
307 
308  template <typename T>
309  static void ResizeDouble(std::vector<T>& vect)
310  {
311  if (SocketEngine::CurrentSetSize > vect.size())
312  vect.resize(SocketEngine::CurrentSetSize * 2);
313  }
314 
315 public:
316 #ifndef _WIN32
317  typedef iovec IOVector;
318 #else
319  typedef WindowsIOVec IOVector;
320 #endif
321 
330  static void Init();
331 
336  static void Deinit();
337 
345  static bool AddFd(EventHandler* eh, int event_mask);
346 
358  static void ChangeEventMask(EventHandler* eh, int event_mask);
359 
365  static size_t GetMaxFds() { return MaxSetSize; }
366 
370  static size_t GetUsedFds() { return CurrentSetSize; }
371 
380  static void DelFd(EventHandler* eh);
381 
387  static bool HasFd(int fd);
388 
394  static EventHandler* GetRef(int fd);
395 
403  static int DispatchEvents();
404 
408  static void DispatchTrialWrites();
409 
413  static bool BoundsCheckFd(EventHandler* eh);
414 
422  static int Accept(EventHandler* fd, sockaddr *addr, socklen_t *addrlen);
423 
428  static int Close(EventHandler* eh);
429 
435  static int Close(int fd);
436 
445  static int Send(EventHandler* fd, const void *buf, size_t len, int flags);
446 
455  static int WriteV(EventHandler* fd, const IOVector* iov, int count);
456 
457 #ifdef _WIN32
465  static int WriteV(EventHandler* fd, const iovec* iov, int count);
466 #endif
467 
476  static int Recv(EventHandler* fd, void *buf, size_t len, int flags);
477 
488  static int RecvFrom(EventHandler* fd, void *buf, size_t len, int flags, sockaddr *from, socklen_t *fromlen);
489 
499  static int SendTo(EventHandler* fd, const void* buf, size_t len, int flags, const irc::sockets::sockaddrs& address);
500 
507  static int Connect(EventHandler* fd, const irc::sockets::sockaddrs& address);
508 
513  static int Blocking(int fd);
514 
519  static int NonBlocking(int fd);
520 
527  static int Shutdown(EventHandler* fd, int how);
528 
533  static int Shutdown(int fd, int how);
534 
539  static int Bind(int fd, const irc::sockets::sockaddrs& addr);
540 
545  static int Listen(int sockfd, int backlog);
546 
549  static void SetReuse(int sockfd);
550 
558  static void RecoverFromFork();
559 
562  static const Statistics& GetStats() { return stats; }
563 
567  static bool IgnoreError();
568 
571  static std::string LastError();
572 
575  static std::string GetError(int errnum);
576 };
577 
579 {
580  if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
581  return true;
582 
583 #ifdef _WIN32
584  if (WSAGetLastError() == WSAEWOULDBLOCK)
585  return true;
586 #endif
587 
588  return false;
589 }
Definition: socketengine.h:154
bool HasFd() const
Definition: socketengine.h:182
int GetFd() const
Definition: socketengine.h:179
virtual void OnEventHandlerRead()=0
virtual ~EventHandler()
Definition: socketengine.h:199
int fd
Definition: socketengine.h:168
Definition: socketengine.h:233
Statistics()
Definition: socketengine.h:246
Definition: socketengine.h:228
static size_t GetMaxFds()
Definition: socketengine.h:365
static bool IgnoreError()
Definition: socketengine.h:578
static size_t GetUsedFds()
Definition: socketengine.h:370
static const Statistics & GetStats()
Definition: socketengine.h:562
Definition: base.h:46
Definition: inspircd_win32wrapper.h:177
Definition: inspircd_win32wrapper.h:170
Definition: socket.h:63