anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
socketengine_kqueue.cpp (2613B)
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 #include <sys/types.h> 20 #include <sys/event.h> 21 #include <sys/time.h> 22 #include <errno.h> 23 24 static int kq_fd; 25 static std::vector<struct kevent> change_events, event_events; 26 static unsigned change_count; 27 28 static inline struct kevent *GetChangeEvent() 29 { 30 if (change_count == change_events.size()) 31 change_events.resize(change_count * 2); 32 33 return &change_events[change_count++]; 34 } 35 36 void SocketEngine::Init() 37 { 38 kq_fd = kqueue(); 39 40 if (kq_fd < 0) 41 throw SocketException("Unable to create kqueue engine: " + Anope::LastError()); 42 43 change_events.resize(DefaultSize); 44 event_events.resize(DefaultSize); 45 } 46 47 void SocketEngine::Shutdown() 48 { 49 while (!Sockets.empty()) 50 delete Sockets.begin()->second; 51 } 52 53 void SocketEngine::Change(Socket *s, bool set, SocketFlag flag) 54 { 55 if (set == s->flags[flag]) 56 return; 57 58 s->flags[flag] = set; 59 60 int mod; 61 if (flag == SF_READABLE) 62 mod = EVFILT_READ; 63 else if (flag == SF_WRITABLE) 64 mod = EVFILT_WRITE; 65 else 66 return; 67 68 struct kevent *event = GetChangeEvent(); 69 EV_SET(event, s->GetFD(), mod, set ? EV_ADD : EV_DELETE, 0, 0, NULL); 70 } 71 72 void SocketEngine::Process() 73 { 74 if (Sockets.size() > event_events.size()) 75 event_events.resize(event_events.size() * 2); 76 77 static timespec kq_timespec = { Config->ReadTimeout, 0 }; 78 int total = kevent(kq_fd, &change_events.front(), change_count, &event_events.front(), event_events.size(), &kq_timespec); 79 change_count = 0; 80 Anope::CurTime = time(NULL); 81 82 /* EINTR can be given if the read timeout expires */ 83 if (total == -1) 84 { 85 if (errno != EINTR) 86 Log() << "SockEngine::Process(): error: " << Anope::LastError(); 87 return; 88 } 89 90 for (int i = 0; i < total; ++i) 91 { 92 struct kevent &event = event_events[i]; 93 if (event.flags & EV_ERROR) 94 continue; 95 96 std::map<int, Socket *>::iterator it = Sockets.find(event.ident); 97 if (it == Sockets.end()) 98 continue; 99 Socket *s = it->second; 100 101 if (event.flags & EV_EOF) 102 { 103 s->ProcessError(); 104 delete s; 105 continue; 106 } 107 108 if (!s->Process()) 109 { 110 if (s->flags[SF_DEAD]) 111 delete s; 112 continue; 113 } 114 115 if (event.filter == EVFILT_READ && !s->ProcessRead()) 116 s->flags[SF_DEAD] = true; 117 else if (event.filter == EVFILT_WRITE && !s->ProcessWrite()) 118 s->flags[SF_DEAD] = true; 119 120 if (s->flags[SF_DEAD]) 121 delete s; 122 } 123 }