diff options
author | Adam <Adam@anope.org> | 2012-11-01 13:32:38 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2012-11-01 14:47:23 -0400 |
commit | 90930619bc124e94bac5048c0b13c3f4748b559d (patch) | |
tree | cbe2325f6295aa188a6dd0f0d56d336eab060bbe /src/socketengines | |
parent | 5b1c8230191fa626ef9210c5035f14a8df4c0ed6 (diff) |
Fixed quite a bit of dumbness with m_ssl. Had to
modify socketengines to allow polling for write &
no read, but is it cleaner now. Made m_httpd able
to listen using SSL.
Diffstat (limited to 'src/socketengines')
-rw-r--r-- | src/socketengines/pipeengine_pipe.cpp | 5 | ||||
-rw-r--r-- | src/socketengines/socketengine_epoll.cpp | 120 | ||||
-rw-r--r-- | src/socketengines/socketengine_kqueue.cpp | 111 | ||||
-rw-r--r-- | src/socketengines/socketengine_poll.cpp | 143 | ||||
-rw-r--r-- | src/socketengines/socketengine_select.cpp | 87 |
5 files changed, 191 insertions, 275 deletions
diff --git a/src/socketengines/pipeengine_pipe.cpp b/src/socketengines/pipeengine_pipe.cpp index dbded29b4..ac3a9cb2c 100644 --- a/src/socketengines/pipeengine_pipe.cpp +++ b/src/socketengines/pipeengine_pipe.cpp @@ -27,12 +27,13 @@ Pipe::Pipe() : Socket(-1), WritePipe(-1) flags = fcntl(fds[1], F_GETFL, 0); fcntl(fds[1], F_SETFL, flags | O_NONBLOCK); - this->~Pipe(); + this->~Socket(); this->Sock = fds[0]; this->WritePipe = fds[1]; - SocketEngine::AddSocket(this); + SocketEngine::Sockets[this->Sock] = this; + SocketEngine::Change(this, true, SF_READABLE); } Pipe::~Pipe() diff --git a/src/socketengines/socketengine_epoll.cpp b/src/socketengines/socketengine_epoll.cpp index 481551289..41f67ebcc 100644 --- a/src/socketengines/socketengine_epoll.cpp +++ b/src/socketengines/socketengine_epoll.cpp @@ -19,107 +19,66 @@ #include <ulimit.h> #include <errno.h> -static long max; static int EngineHandle; -static epoll_event *events; +static std::vector<epoll_event> events; void SocketEngine::Init() { - max = ulimit(4, 0); - - if (max <= 0) - throw SocketException("Can't determine maximum number of open sockets"); - - EngineHandle = epoll_create(max / 4); + EngineHandle = epoll_create(4); if (EngineHandle == -1) throw SocketException("Could not initialize epoll socket engine: " + Anope::LastError()); - - events = new epoll_event[max]; - memset(events, 0, sizeof(epoll_event) * max); + + events.resize(DefaultSize); } void SocketEngine::Shutdown() { - for (std::map<int, Socket *>::const_iterator it = Sockets.begin(), it_end = Sockets.end(); it != it_end;) - { - Socket *s = it->second; - ++it; - delete s; - } - Sockets.clear(); - - delete [] events; -} - -void SocketEngine::AddSocket(Socket *s) -{ - epoll_event ev; - - memset(&ev, 0, sizeof(ev)); - - ev.events = EPOLLIN; - ev.data.fd = s->GetFD(); - - if (epoll_ctl(EngineHandle, EPOLL_CTL_ADD, ev.data.fd, &ev) == -1) - throw SocketException("Unable to add fd " + stringify(ev.data.fd) + " to epoll: " + Anope::LastError()); - - Sockets[ev.data.fd] = s; + while (!Sockets.empty()) + delete Sockets.begin()->second; } -void SocketEngine::DelSocket(Socket *s) +void SocketEngine::Change(Socket *s, bool set, SocketFlag flag) { - epoll_event ev; - - memset(&ev, 0, sizeof(ev)); - - ev.data.fd = s->GetFD(); - - if (epoll_ctl(EngineHandle, EPOLL_CTL_DEL, ev.data.fd, &ev) == -1) - throw SocketException("Unable to remove fd " + stringify(ev.data.fd) + " from epoll: " + Anope::LastError()); - - Sockets.erase(ev.data.fd); -} - -void SocketEngine::MarkWritable(Socket *s) -{ - if (s->HasFlag(SF_WRITABLE)) + if (set == s->HasFlag(flag)) return; - epoll_event ev; + bool before_registered = s->HasFlag(SF_READABLE) || s->HasFlag(SF_WRITABLE); - memset(&ev, 0, sizeof(ev)); - - ev.events = EPOLLIN | EPOLLOUT; - ev.data.fd = s->GetFD(); - - if (epoll_ctl(EngineHandle, EPOLL_CTL_MOD, ev.data.fd, &ev) == -1) - throw SocketException("Unable to mark fd " + stringify(ev.data.fd) + " as writable in epoll: " + Anope::LastError()); - - s->SetFlag(SF_WRITABLE); -} - -void SocketEngine::ClearWritable(Socket *s) -{ - if (!s->HasFlag(SF_WRITABLE)) - return; + if (set) + s->SetFlag(flag); + else + s->UnsetFlag(flag); + + bool now_registered = s->HasFlag(SF_READABLE) || s->HasFlag(SF_WRITABLE); epoll_event ev; memset(&ev, 0, sizeof(ev)); - ev.events = EPOLLIN; + ev.events = (s->HasFlag(SF_READABLE) ? EPOLLIN : 0) | (s->HasFlag(SF_WRITABLE) ? EPOLLOUT : 0); ev.data.fd = s->GetFD(); - if (epoll_ctl(EngineHandle, EPOLL_CTL_MOD, ev.data.fd, &ev) == -1) - throw SocketException("Unable clear mark fd " + stringify(ev.data.fd) + " as writable in epoll: " + Anope::LastError()); - - s->UnsetFlag(SF_WRITABLE); + int mod; + if (!before_registered && now_registered) + mod = EPOLL_CTL_ADD; + else if (before_registered && !now_registered) + mod = EPOLL_CTL_DEL; + else if (before_registered && now_registered) + mod = EPOLL_CTL_MOD; + else + return; + + if (epoll_ctl(EngineHandle, mod, ev.data.fd, &ev) == -1) + throw SocketException("Unable to epoll_ctl() fd " + stringify(ev.data.fd) + " to epoll: " + Anope::LastError()); } void SocketEngine::Process() { - int total = epoll_wait(EngineHandle, events, max - 1, Config->ReadTimeout * 1000); + if (Sockets.size() > events.size()) + events.resize(events.size() * 2); + + int total = epoll_wait(EngineHandle, &events.front(), events.size(), Config->ReadTimeout * 1000); Anope::CurTime = time(NULL); /* EINTR can be given if the read timeout expires */ @@ -132,28 +91,31 @@ void SocketEngine::Process() for (int i = 0; i < total; ++i) { - epoll_event *ev = &events[i]; + epoll_event &ev = events[i]; - std::map<int, Socket *>::iterator it = Sockets.find(ev->data.fd); + std::map<int, Socket *>::iterator it = Sockets.find(ev.data.fd); if (it == Sockets.end()) continue; Socket *s = it->second; - if (ev->events & (EPOLLHUP | EPOLLERR)) + if (ev.events & (EPOLLHUP | EPOLLERR)) { s->ProcessError(); - s->SetFlag(SF_DEAD); delete s; continue; } if (!s->Process()) + { + if (s->HasFlag(SF_DEAD)) + delete s; continue; + } - if ((ev->events & EPOLLIN) && !s->ProcessRead()) + if ((ev.events & EPOLLIN) && !s->ProcessRead()) s->SetFlag(SF_DEAD); - if ((ev->events & EPOLLOUT) && !s->ProcessWrite()) + if ((ev.events & EPOLLOUT) && !s->ProcessWrite()) s->SetFlag(SF_DEAD); if (s->HasFlag(SF_DEAD)) diff --git a/src/socketengines/socketengine_kqueue.cpp b/src/socketengines/socketengine_kqueue.cpp index cc5909934..549773d75 100644 --- a/src/socketengines/socketengine_kqueue.cpp +++ b/src/socketengines/socketengine_kqueue.cpp @@ -11,8 +11,8 @@ #include "services.h" #include "anope.h" -#include "socketengine.h" #include "sockets.h" +#include "socketengine.h" #include "logger.h" #include "config.h" @@ -21,19 +21,14 @@ #include <sys/time.h> #include <errno.h> -static int kq_fd, max_fds; -static struct kevent *change_events, *event_events; -static int change_count; +static int kq_fd; +static std::vector<struct kevent> change_events, event_events; +static unsigned change_count; -static struct kevent *GetChangeEvent() +static inline struct kevent *GetChangeEvent() { - if (change_count == max_fds) - { - timespec zero_timespec = { 0, 0 }; - for (int i = 0; i < change_count; ++i) - kevent(kq_fd, &change_events[i], 1, NULL, 0, &zero_timespec); - change_count = 0; - } + if (change_count == change_events.size()) + change_events.resize(change_count * 2); return &change_events[change_count++]; } @@ -41,78 +36,49 @@ static struct kevent *GetChangeEvent() void SocketEngine::Init() { kq_fd = kqueue(); - max_fds = getdtablesize(); if (kq_fd < 0) throw SocketException("Unable to create kqueue engine: " + Anope::LastError()); - else if (max_fds <= 0) - throw SocketException("Can't determine maximum number of open sockets"); - - change_events = new struct kevent[max_fds]; - event_events = new struct kevent[max_fds]; - - change_count = 0; + + change_events.resize(DefaultSize); + event_events.resize(DefaultSize); } void SocketEngine::Shutdown() { - for (std::map<int, Socket *>::const_iterator it = Sockets.begin(), it_end = Sockets.end(); it != it_end;) - { - Socket *s = it->second; - ++it; - delete s; - } - Sockets.clear(); - - delete [] change_events; - delete [] event_events; -} - -void SocketEngine::AddSocket(Socket *s) -{ - struct kevent *event = GetChangeEvent(); - EV_SET(event, s->GetFD(), EVFILT_READ, EV_ADD, 0, 0, NULL); - - Sockets[s->GetFD()] = s; -} - -void SocketEngine::DelSocket(Socket *s) -{ - struct kevent *event = GetChangeEvent(); - EV_SET(event, s->GetFD(), EVFILT_READ, EV_DELETE, 0, 0, NULL); - - event = GetChangeEvent(); - EV_SET(event, s->GetFD(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL); - - Sockets.erase(s->GetFD()); + while (!Sockets.empty()) + delete Sockets.begin()->second; } -void SocketEngine::MarkWritable(Socket *s) +void SocketEngine::Change(Socket *s, bool set, SocketFlag flag) { - if (s->HasFlag(SF_WRITABLE)) + if (set == s->HasFlag(flag)) return; - struct kevent *event = GetChangeEvent(); - EV_SET(event, s->GetFD(), EVFILT_WRITE, EV_ADD, 0, 0, NULL); - - s->SetFlag(SF_WRITABLE); -} - -void SocketEngine::ClearWritable(Socket *s) -{ - if (!s->HasFlag(SF_WRITABLE)) + if (set) + s->SetFlag(flag); + else + s->UnsetFlag(flag); + + int mod; + if (flag == SF_READABLE) + mod = EVFILT_READ; + else if (flag == SF_WRITABLE) + mod = EVFILT_WRITE; + else return; struct kevent *event = GetChangeEvent(); - EV_SET(event, s->GetFD(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL); - - s->UnsetFlag(SF_WRITABLE); + EV_SET(event, s->GetFD(), mod, set ? EV_ADD : EV_DELETE, 0, 0, NULL); } void SocketEngine::Process() { + if (Sockets.size() > event_events.size()) + event_events.resize(event_events.size() * 2); + static timespec kq_timespec = { Config->ReadTimeout, 0 }; - int total = kevent(kq_fd, change_events, change_count, event_events, max_fds, &kq_timespec); + int total = kevent(kq_fd, &change_events.front(), change_count, &event_events.front(), event_events.size(), &kq_timespec); change_count = 0; Anope::CurTime = time(NULL); @@ -126,29 +92,32 @@ void SocketEngine::Process() for (int i = 0; i < total; ++i) { - struct kevent *event = &event_events[i]; - if (event->flags & EV_ERROR) + struct kevent &event = event_events[i]; + if (event.flags & EV_ERROR) continue; - std::map<int, Socket *>::iterator it = Sockets.find(event->ident); + std::map<int, Socket *>::iterator it = Sockets.find(event.ident); if (it == Sockets.end()) continue; Socket *s = it->second; - if (event->flags & EV_EOF) + if (event.flags & EV_EOF) { s->ProcessError(); - s->SetFlag(SF_DEAD); delete s; continue; } if (!s->Process()) + { + if (s->HasFlag(SF_DEAD)) + delete s; continue; + } - if (event->filter == EVFILT_READ && !s->ProcessRead()) + if (event.filter == EVFILT_READ && !s->ProcessRead()) s->SetFlag(SF_DEAD); - else if (event->filter == EVFILT_WRITE && !s->ProcessWrite()) + else if (event.filter == EVFILT_WRITE && !s->ProcessWrite()) s->SetFlag(SF_DEAD); if (s->HasFlag(SF_DEAD)) diff --git a/src/socketengines/socketengine_poll.cpp b/src/socketengines/socketengine_poll.cpp index 766fea601..6b5d57a6e 100644 --- a/src/socketengines/socketengine_poll.cpp +++ b/src/socketengines/socketengine_poll.cpp @@ -11,10 +11,9 @@ #include "services.h" #include "anope.h" -#include "socketengine.h" #include "sockets.h" +#include "socketengine.h" #include "config.h" -#include "logger.h" #include <errno.h> @@ -32,121 +31,96 @@ # define POLLRDHUP POLLHUP #endif -static long max; -static pollfd *events; -static int SocketCount; -static std::map<int, int> socket_positions; +static std::vector<pollfd> events; +static unsigned SocketCount; +static std::map<int, unsigned> socket_positions; void SocketEngine::Init() { - SocketCount = 0; - - rlimit fd_limit; - if (getrlimit(RLIMIT_NOFILE, &fd_limit) == -1) - throw CoreException(Anope::LastError()); - - max = fd_limit.rlim_cur; - - events = new pollfd[max]; + events.resize(DefaultSize); } void SocketEngine::Shutdown() { - for (std::map<int, Socket *>::const_iterator it = Sockets.begin(), it_end = Sockets.end(); it != it_end;) - { - Socket *s = it->second; - ++it; - delete s; - } - Sockets.clear(); - - delete [] events; + while (!Sockets.empty()) + delete Sockets.begin()->second; } -void SocketEngine::AddSocket(Socket *s) +void SocketEngine::Change(Socket *s, bool set, SocketFlag flag) { - if (SocketCount == max) - throw SocketException("Unable to add fd " + stringify(s->GetFD()) + " to poll: " + Anope::LastError()); - - pollfd *ev = &events[SocketCount]; - ev->fd = s->GetFD(); - ev->events = POLLIN; - ev->revents = 0; - - Sockets[ev->fd] = s; - socket_positions[ev->fd] = SocketCount; + if (set == s->HasFlag(flag)) + return; - ++SocketCount; -} + bool before_registered = s->HasFlag(SF_READABLE) || s->HasFlag(SF_WRITABLE); -void SocketEngine::DelSocket(Socket *s) -{ - std::map<int, int>::iterator pos = socket_positions.find(s->GetFD()); - if (pos == socket_positions.end()) - throw SocketException("Unable to remove fd " + stringify(s->GetFD()) + " from poll"); + if (set) + s->SetFlag(flag); + else + s->UnsetFlag(flag); + + bool now_registered = s->HasFlag(SF_READABLE) || s->HasFlag(SF_WRITABLE); - if (pos->second != SocketCount - 1) + if (!before_registered && now_registered) { - pollfd *ev = &events[pos->second], - *last_ev = &events[SocketCount - 1]; + if (SocketCount >= events.size()) + events.resize(events.size() * 2); - ev->fd = last_ev->fd; - ev->events = last_ev->events; - ev->revents = last_ev->revents; + pollfd &ev = events[SocketCount]; + memset(&ev, 0, sizeof(ev)); - socket_positions[ev->fd] = pos->second; - } - - Sockets.erase(s->GetFD()); - socket_positions.erase(pos); - - --SocketCount; -} + ev.fd = s->GetFD(); + ev.events = (s->HasFlag(SF_READABLE) ? POLLIN : 0) | (s->HasFlag(SF_WRITABLE) ? POLLOUT : 0); -void SocketEngine::MarkWritable(Socket *s) -{ - if (s->HasFlag(SF_WRITABLE)) - return; - - std::map<int, int>::iterator pos = socket_positions.find(s->GetFD()); - if (pos == socket_positions.end()) - throw SocketException("Unable to mark fd " + stringify(s->GetFD()) + " as writable in poll"); + socket_positions[ev.fd] = SocketCount; + ++SocketCount; + } + else if (before_registered && !now_registered) + { + std::map<int, unsigned>::iterator pos = socket_positions.find(s->GetFD()); + if (pos == socket_positions.end()) + throw SocketException("Unable to remove fd " + stringify(s->GetFD()) + " from poll, it does not exist?"); - pollfd *ev = &events[pos->second]; - ev->events |= POLLOUT; - - s->SetFlag(SF_WRITABLE); -} + if (pos->second != SocketCount - 1) + { + pollfd &ev = events[pos->second], + &last_ev = events[SocketCount - 1]; -void SocketEngine::ClearWritable(Socket *s) -{ - if (!s->HasFlag(SF_WRITABLE)) - return; + ev = last_ev; - std::map<int, int>::iterator pos = socket_positions.find(s->GetFD()); - if (pos == socket_positions.end()) - throw SocketException("Unable clear mark fd " + stringify(s->GetFD()) + " as writable in poll"); + socket_positions[ev.fd] = pos->second; + } - pollfd *ev = &events[pos->second]; - ev->events &= ~POLLOUT; + socket_positions.erase(pos); + --SocketCount; + } + else if (before_registered && now_registered) + { + std::map<int, unsigned>::iterator pos = socket_positions.find(s->GetFD()); + if (pos == socket_positions.end()) + throw SocketException("Unable to modify fd " + stringify(s->GetFD()) + " in poll, it does not exist?"); - s->UnsetFlag(SF_WRITABLE); + pollfd &ev = events[pos->second]; + ev.events = (s->HasFlag(SF_READABLE) ? POLLIN : 0) | (s->HasFlag(SF_WRITABLE) ? POLLOUT : 0); + } } void SocketEngine::Process() { - int total = poll(events, SocketCount, Config->ReadTimeout * 1000); + if (Sockets.size() > events.size()) + events.resize(events.size() * 2); + + int total = poll(&events.front(), events.size(), Config->ReadTimeout * 1000); Anope::CurTime = time(NULL); /* EINTR can be given if the read timeout expires */ - if (total == -1) + if (total < 0) { if (errno != EINTR) Log() << "SockEngine::Process(): error: " << Anope::LastError(); return; } - for (int i = 0, processed = 0; i < SocketCount && processed != total; ++i) + for (unsigned i = 0, processed = 0; i < SocketCount && processed != static_cast<unsigned>(total); ++i) { pollfd *ev = &events[i]; @@ -161,13 +135,16 @@ void SocketEngine::Process() if (ev->revents & (POLLERR | POLLRDHUP)) { s->ProcessError(); - s->SetFlag(SF_DEAD); delete s; continue; } if (!s->Process()) + { + if (s->HasFlag(SF_DEAD)) + delete s; continue; + } if ((ev->revents & POLLIN) && !s->ProcessRead()) s->SetFlag(SF_DEAD); diff --git a/src/socketengines/socketengine_select.cpp b/src/socketengines/socketengine_select.cpp index 2398047f3..0d8df20a2 100644 --- a/src/socketengines/socketengine_select.cpp +++ b/src/socketengines/socketengine_select.cpp @@ -11,8 +11,8 @@ #include "services.h" #include "anope.h" -#include "socketengine.h" #include "sockets.h" +#include "socketengine.h" #include "logger.h" #include "config.h" @@ -28,56 +28,60 @@ static fd_set WriteFDs; void SocketEngine::Init() { - MaxFD = 0; - FDCount = 0; FD_ZERO(&ReadFDs); FD_ZERO(&WriteFDs); } void SocketEngine::Shutdown() { - for (std::map<int, Socket *>::const_iterator it = Sockets.begin(), it_end = Sockets.end(); it != it_end;) - { - Socket *s = it->second; - ++it; - delete s; - } - Sockets.clear(); + while (!Sockets.empty()) + delete Sockets.begin()->second; } -void SocketEngine::AddSocket(Socket *s) +void SocketEngine::Change(Socket *s, bool set, SocketFlag flag) { - if (s->GetFD() > MaxFD) - MaxFD = s->GetFD(); - FD_SET(s->GetFD(), &ReadFDs); - Sockets[s->GetFD()] = s; - ++FDCount; -} + if (set == s->HasFlag(flag)) + return; -void SocketEngine::DelSocket(Socket *s) -{ - if (s->GetFD() == MaxFD) - --MaxFD; - FD_CLR(s->GetFD(), &ReadFDs); - FD_CLR(s->GetFD(), &WriteFDs); - Sockets.erase(s->GetFD()); - --FDCount; -} + bool before_registered = s->HasFlag(SF_READABLE) || s->HasFlag(SF_WRITABLE); -void SocketEngine::MarkWritable(Socket *s) -{ - if (s->HasFlag(SF_WRITABLE)) - return; - FD_SET(s->GetFD(), &WriteFDs); - s->SetFlag(SF_WRITABLE); -} + if (set) + s->SetFlag(flag); + else + s->UnsetFlag(flag); + + bool now_registered = s->HasFlag(SF_READABLE) || s->HasFlag(SF_WRITABLE); -void SocketEngine::ClearWritable(Socket *s) -{ - if (!s->HasFlag(SF_WRITABLE)) - return; - FD_CLR(s->GetFD(), &WriteFDs); - s->UnsetFlag(SF_WRITABLE); + if (!before_registered && now_registered) + { + if (s->GetFD() > MaxFD) + MaxFD = s->GetFD(); + if (s->HasFlag(SF_READABLE)) + FD_SET(s->GetFD(), &ReadFDs); + if (s->HasFlag(SF_WRITABLE)) + FD_SET(s->GetFD(), &WriteFDs); + ++FDCount; + } + else if (before_registered && !now_registered) + { + if (s->GetFD() == MaxFD) + --MaxFD; + FD_CLR(s->GetFD(), &ReadFDs); + FD_CLR(s->GetFD(), &WriteFDs); + --FDCount; + } + else if (before_registered && now_registered) + { + if (s->HasFlag(SF_READABLE)) + FD_SET(s->GetFD(), &ReadFDs); + else + FD_CLR(s->GetFD(), &ReadFDs); + + if (s->HasFlag(SF_WRITABLE)) + FD_SET(s->GetFD(), &WriteFDs); + else + FD_CLR(s->GetFD(), &WriteFDs); + } } void SocketEngine::Process() @@ -123,13 +127,16 @@ void SocketEngine::Process() if (has_error) { s->ProcessError(); - s->SetFlag(SF_DEAD); delete s; continue; } if (!s->Process()) + { + if (s->HasFlag(SF_DEAD)) + delete s; continue; + } if (has_read && !s->ProcessRead()) s->SetFlag(SF_DEAD); |