anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
socketengine_poll.cpp (3342B)
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 "config.h" 17 18 #include <errno.h> 19 20 #ifndef _WIN32 21 # include <sys/poll.h> 22 # include <poll.h> 23 # include <sys/types.h> 24 # include <sys/time.h> 25 # include <sys/resource.h> 26 # ifndef POLLRDHUP 27 # define POLLRDHUP 0 28 # endif 29 #else 30 # define poll WSAPoll 31 # define POLLRDHUP POLLHUP 32 #endif 33 34 static std::vector<pollfd> events; 35 static std::map<int, unsigned> socket_positions; 36 37 void SocketEngine::Init() 38 { 39 events.resize(DefaultSize); 40 } 41 42 void SocketEngine::Shutdown() 43 { 44 while (!Sockets.empty()) 45 delete Sockets.begin()->second; 46 } 47 48 void SocketEngine::Change(Socket *s, bool set, SocketFlag flag) 49 { 50 if (set == s->flags[flag]) 51 return; 52 53 bool before_registered = s->flags[SF_READABLE] || s->flags[SF_WRITABLE]; 54 55 s->flags[flag] = set; 56 57 bool now_registered = s->flags[SF_READABLE] || s->flags[SF_WRITABLE]; 58 59 if (!before_registered && now_registered) 60 { 61 pollfd ev; 62 memset(&ev, 0, sizeof(ev)); 63 64 ev.fd = s->GetFD(); 65 ev.events = (s->flags[SF_READABLE] ? POLLIN : 0) | (s->flags[SF_WRITABLE] ? POLLOUT : 0); 66 67 socket_positions[ev.fd] = events.size(); 68 events.push_back(ev); 69 } 70 else if (before_registered && !now_registered) 71 { 72 std::map<int, unsigned>::iterator pos = socket_positions.find(s->GetFD()); 73 if (pos == socket_positions.end()) 74 throw SocketException("Unable to remove fd " + stringify(s->GetFD()) + " from poll, it does not exist?"); 75 76 if (pos->second != events.size() - 1) 77 { 78 pollfd &ev = events[pos->second], 79 &last_ev = events[events.size() - 1]; 80 81 ev = last_ev; 82 83 socket_positions[ev.fd] = pos->second; 84 } 85 86 socket_positions.erase(pos); 87 events.pop_back(); 88 } 89 else if (before_registered && now_registered) 90 { 91 std::map<int, unsigned>::iterator pos = socket_positions.find(s->GetFD()); 92 if (pos == socket_positions.end()) 93 throw SocketException("Unable to modify fd " + stringify(s->GetFD()) + " in poll, it does not exist?"); 94 95 pollfd &ev = events[pos->second]; 96 ev.events = (s->flags[SF_READABLE] ? POLLIN : 0) | (s->flags[SF_WRITABLE] ? POLLOUT : 0); 97 } 98 } 99 100 void SocketEngine::Process() 101 { 102 int total = poll(&events.front(), events.size(), Config->ReadTimeout * 1000); 103 Anope::CurTime = time(NULL); 104 105 /* EINTR can be given if the read timeout expires */ 106 if (total < 0) 107 { 108 if (errno != EINTR) 109 Log() << "SockEngine::Process(): error: " << Anope::LastError(); 110 return; 111 } 112 113 for (unsigned i = 0, processed = 0; i < events.size() && processed != static_cast<unsigned>(total); ++i) 114 { 115 pollfd *ev = &events[i]; 116 117 if (ev->revents != 0) 118 ++processed; 119 120 std::map<int, Socket *>::iterator it = Sockets.find(ev->fd); 121 if (it == Sockets.end()) 122 continue; 123 Socket *s = it->second; 124 125 if (ev->revents & (POLLERR | POLLRDHUP)) 126 { 127 s->ProcessError(); 128 delete s; 129 continue; 130 } 131 132 if (!s->Process()) 133 { 134 if (s->flags[SF_DEAD]) 135 delete s; 136 continue; 137 } 138 139 if ((ev->revents & POLLIN) && !s->ProcessRead()) 140 s->flags[SF_DEAD] = true; 141 142 if ((ev->revents & POLLOUT) && !s->ProcessWrite()) 143 s->flags[SF_DEAD] = true; 144 145 if (s->flags[SF_DEAD]) 146 delete s; 147 } 148 }