Anope IRC Services  Version 2.0
socketengine_select.cpp
Go to the documentation of this file.
1 /*
2  *
3  * (C) 2003-2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  */
11 
12 #include "services.h"
13 #include "anope.h"
14 #include "sockets.h"
15 #include "socketengine.h"
16 #include "logger.h"
17 #include "config.h"
18 
19 #ifdef _AIX
20 # undef FD_ZERO
21 # define FD_ZERO(p) memset((p), 0, sizeof(*(p)))
22 #endif /* _AIX */
23 
24 static int MaxFD;
25 static unsigned FDCount;
26 static fd_set ReadFDs;
27 static fd_set WriteFDs;
28 
29 void SocketEngine::Init()
30 {
31  FD_ZERO(&ReadFDs);
32  FD_ZERO(&WriteFDs);
33 }
34 
36 {
37  while (!Sockets.empty())
38  delete Sockets.begin()->second;
39 }
40 
41 void SocketEngine::Change(Socket *s, bool set, SocketFlag flag)
42 {
43  if (set == s->flags[flag])
44  return;
45 
46  bool before_registered = s->flags[SF_READABLE] || s->flags[SF_WRITABLE];
47 
48  s->flags[flag] = set;
49 
50  bool now_registered = s->flags[SF_READABLE] || s->flags[SF_WRITABLE];
51 
52  if (!before_registered && now_registered)
53  {
54  if (s->GetFD() > MaxFD)
55  MaxFD = s->GetFD();
56  if (s->flags[SF_READABLE])
57  FD_SET(s->GetFD(), &ReadFDs);
58  if (s->flags[SF_WRITABLE])
59  FD_SET(s->GetFD(), &WriteFDs);
60  ++FDCount;
61  }
62  else if (before_registered && !now_registered)
63  {
64  if (s->GetFD() == MaxFD)
65  --MaxFD;
66  FD_CLR(s->GetFD(), &ReadFDs);
67  FD_CLR(s->GetFD(), &WriteFDs);
68  --FDCount;
69  }
70  else if (before_registered && now_registered)
71  {
72  if (s->flags[SF_READABLE])
73  FD_SET(s->GetFD(), &ReadFDs);
74  else
75  FD_CLR(s->GetFD(), &ReadFDs);
76 
77  if (s->flags[SF_WRITABLE])
78  FD_SET(s->GetFD(), &WriteFDs);
79  else
80  FD_CLR(s->GetFD(), &WriteFDs);
81  }
82 }
83 
85 {
86  fd_set rfdset = ReadFDs, wfdset = WriteFDs, efdset = ReadFDs;
87  timeval tval;
88  tval.tv_sec = Config->ReadTimeout;
89  tval.tv_usec = 0;
90 
91 #ifdef _WIN32
92  /* We can use the socket engine to "sleep" services for a period of
93  * time between connections to the uplink, which allows modules,
94  * timers, etc to function properly. Windows, being as useful as it is,
95  * does not allow to select() on 0 sockets and will immediately return error.
96  * Thus:
97  */
98  if (FDCount == 0)
99  {
100  sleep(tval.tv_sec);
101  return;
102  }
103 #endif
104 
105  int sresult = select(MaxFD + 1, &rfdset, &wfdset, &efdset, &tval);
106  Anope::CurTime = time(NULL);
107 
108  if (sresult == -1)
109  {
110  Log() << "SockEngine::Process(): error: " << Anope::LastError();
111  }
112  else if (sresult)
113  {
114  int processed = 0;
115  for (std::map<int, Socket *>::const_iterator it = Sockets.begin(), it_end = Sockets.end(); it != it_end && processed != sresult;)
116  {
117  Socket *s = it->second;
118  ++it;
119 
120  bool has_read = FD_ISSET(s->GetFD(), &rfdset), has_write = FD_ISSET(s->GetFD(), &wfdset), has_error = FD_ISSET(s->GetFD(), &efdset);
121  if (has_read || has_write || has_error)
122  ++processed;
123 
124  if (has_error)
125  {
126  s->ProcessError();
127  delete s;
128  continue;
129  }
130 
131  if (!s->Process())
132  {
133  if (s->flags[SF_DEAD])
134  delete s;
135  continue;
136  }
137 
138  if (has_read && !s->ProcessRead())
139  s->flags[SF_DEAD] = true;
140 
141  if (has_write && !s->ProcessWrite())
142  s->flags[SF_DEAD] = true;
143 
144  if (s->flags[SF_DEAD])
145  delete s;
146  }
147  }
148 }
149 
std::bitset< SF_SIZE > flags
Definition: sockets.h:203
SocketFlag
Definition: sockets.h:124
static void Init()
CoreExport const string LastError()
Definition: misc.cpp:606
virtual bool Process()
Definition: sockets.cpp:498
virtual bool ProcessRead()
Definition: sockets.cpp:503
virtual bool ProcessWrite()
Definition: sockets.cpp:508
static void Process()
static std::map< int, Socket * > Sockets
Definition: socketengine.h:24
static fd_set ReadFDs
static void Change(Socket *s, bool set, SocketFlag flag)
CoreExport time_t CurTime
Definition: main.cpp:41
int GetFD() const
Definition: sockets.cpp:474
Definition: Config.cs:26
static unsigned FDCount
static void Shutdown()
static fd_set WriteFDs
Definition: logger.h:53
virtual void ProcessError()
Definition: sockets.cpp:513
static int MaxFD