anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
socketengine_select.cpp (3176B)
1 /* 2 * 3 * (C) 2003-2022 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 35 void SocketEngine::Shutdown() 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 84 void SocketEngine::Process() 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 }