summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2012-11-01 13:32:38 -0400
committerAdam <Adam@anope.org>2012-11-01 14:47:23 -0400
commit90930619bc124e94bac5048c0b13c3f4748b559d (patch)
treecbe2325f6295aa188a6dd0f0d56d336eab060bbe /src
parent5b1c8230191fa626ef9210c5035f14a8df4c0ed6 (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')
-rw-r--r--src/dns.cpp17
-rw-r--r--src/socket_clients.cpp4
-rw-r--r--src/socket_transport.cpp10
-rw-r--r--src/socketengines/pipeengine_pipe.cpp5
-rw-r--r--src/socketengines/socketengine_epoll.cpp120
-rw-r--r--src/socketengines/socketengine_kqueue.cpp111
-rw-r--r--src/socketengines/socketengine_poll.cpp143
-rw-r--r--src/socketengines/socketengine_select.cpp87
-rw-r--r--src/sockets.cpp9
9 files changed, 213 insertions, 293 deletions
diff --git a/src/dns.cpp b/src/dns.cpp
index f88e9adfd..29c3134f7 100644
--- a/src/dns.cpp
+++ b/src/dns.cpp
@@ -519,7 +519,7 @@ void DNSManager::TCPSocket::Client::Reply(DNSPacket *p)
{
delete packet;
packet = p;
- SocketEngine::MarkWritable(this);
+ SocketEngine::Change(this, true, SF_WRITABLE);
}
bool DNSManager::TCPSocket::Client::ProcessRead()
@@ -535,9 +535,8 @@ bool DNSManager::TCPSocket::Client::ProcessRead()
short want_len = packet_buffer[0] << 8 | packet_buffer[1];
if (length >= want_len - 2)
{
- int len = length - 2;
- length = 0;
- return DNSEngine->HandlePacket(this, packet_buffer + 2, len, NULL);
+ SocketEngine::Change(this, false, SF_READABLE);
+ return DNSEngine->HandlePacket(this, packet_buffer + 2, length - 2, NULL);
}
return true;
}
@@ -565,7 +564,7 @@ bool DNSManager::TCPSocket::Client::ProcessWrite()
packet = NULL;
}
- SocketEngine::ClearWritable(this);
+ SocketEngine::Change(this, false, SF_WRITABLE);
return true; /* Do not return false here, bind is unhappy we close the connection so soon after sending */
}
@@ -591,7 +590,7 @@ DNSManager::UDPSocket::~UDPSocket()
void DNSManager::UDPSocket::Reply(DNSPacket *p)
{
packets.push_back(p);
- SocketEngine::MarkWritable(this);
+ SocketEngine::Change(this, true, SF_WRITABLE);
}
bool DNSManager::UDPSocket::ProcessRead()
@@ -626,7 +625,7 @@ bool DNSManager::UDPSocket::ProcessWrite()
}
if (packets.empty())
- SocketEngine::ClearWritable(this);
+ SocketEngine::Change(this, false, SF_WRITABLE);
return true;
}
@@ -848,7 +847,7 @@ bool DNSManager::CheckCache(DNSRequest *request)
for (cache_map::iterator it_end = this->cache.upper_bound(request->name); it != it_end; ++it)
{
ResourceRecord &rec = it->second;
- if (rec.created + rec.ttl >= Anope::CurTime)
+ if (rec.created + static_cast<time_t>(rec.ttl) >= Anope::CurTime)
record.answers.push_back(rec);
}
@@ -873,7 +872,7 @@ void DNSManager::Tick(time_t now)
it_next = it;
++it_next;
- if (req.created + req.ttl < now)
+ if (req.created + static_cast<time_t>(req.ttl) < now)
this->cache.erase(it);
}
}
diff --git a/src/socket_clients.cpp b/src/socket_clients.cpp
index 4d3a1e3ee..44d4b873a 100644
--- a/src/socket_clients.cpp
+++ b/src/socket_clients.cpp
@@ -56,8 +56,9 @@ void ConnectionSocket::OnConnect()
{
}
-void ConnectionSocket::OnError(const Anope::string &)
+void ConnectionSocket::OnError(const Anope::string &error)
{
+ Log(LOG_DEBUG) << "Socket error: " << error;
}
ClientSocket::ClientSocket(ListenSocket *ls, const sockaddrs &addr) : LS(ls), clientaddr(addr)
@@ -97,5 +98,6 @@ void ClientSocket::OnAccept()
void ClientSocket::OnError(const Anope::string &error)
{
+ Log(LOG_DEBUG) << "Socket error: " << error;
}
diff --git a/src/socket_transport.cpp b/src/socket_transport.cpp
index 30af95226..2297da2b2 100644
--- a/src/socket_transport.cpp
+++ b/src/socket_transport.cpp
@@ -70,7 +70,7 @@ bool BufferedSocket::ProcessWrite()
return false;
this->WriteBuffer = this->WriteBuffer.substr(count);
if (this->WriteBuffer.empty())
- SocketEngine::ClearWritable(this);
+ SocketEngine::Change(this, false, SF_WRITABLE);
return true;
}
@@ -83,7 +83,7 @@ bool BufferedSocket::Read(const Anope::string &buf)
void BufferedSocket::Write(const char *buffer, size_t l)
{
this->WriteBuffer += buffer + Anope::string("\r\n");
- SocketEngine::MarkWritable(this);
+ SocketEngine::Change(this, true, SF_WRITABLE);
}
void BufferedSocket::Write(const char *message, ...)
@@ -152,7 +152,7 @@ bool BinarySocket::ProcessWrite()
{
if (this->WriteBuffer.empty())
{
- SocketEngine::ClearWritable(this);
+ SocketEngine::Change(this, false, SF_WRITABLE);
return true;
}
@@ -173,7 +173,7 @@ bool BinarySocket::ProcessWrite()
}
if (this->WriteBuffer.empty())
- SocketEngine::ClearWritable(this);
+ SocketEngine::Change(this, false, SF_WRITABLE);
return true;
}
@@ -181,7 +181,7 @@ bool BinarySocket::ProcessWrite()
void BinarySocket::Write(const char *buffer, size_t l)
{
this->WriteBuffer.push_back(new DataBlock(buffer, l));
- SocketEngine::MarkWritable(this);
+ SocketEngine::Change(this, true, SF_WRITABLE);
}
void BinarySocket::Write(const char *message, ...)
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);
diff --git a/src/sockets.cpp b/src/sockets.cpp
index 665db5ca2..5cf567de5 100644
--- a/src/sockets.cpp
+++ b/src/sockets.cpp
@@ -384,7 +384,7 @@ void SocketIO::Connect(ConnectionSocket *s, const Anope::string &target, int por
s->OnError(Anope::LastError());
else
{
- SocketEngine::MarkWritable(s);
+ SocketEngine::Change(s, true, SF_WRITABLE);
s->SetFlag(SF_CONNECTING);
}
}
@@ -444,16 +444,19 @@ Socket::Socket(int sock, bool ipv6, int type) : Flags<SocketFlag>(SocketFlagStri
else
this->Sock = sock;
this->SetNonBlocking();
- SocketEngine::AddSocket(this);
+ SocketEngine::Sockets[this->Sock] = this;
+ SocketEngine::Change(this, true, SF_READABLE);
}
/** Default destructor
*/
Socket::~Socket()
{
- SocketEngine::DelSocket(this);
+ SocketEngine::Change(this, false, SF_READABLE);
+ SocketEngine::Change(this, false, SF_WRITABLE);
anope_close(this->Sock);
this->IO->Destroy();
+ SocketEngine::Sockets.erase(this->Sock);
}
/** Get the socket FD for this socket