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 }