1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2009 InspIRCd Development Team
6 * See: http://www.inspircd.org/wiki/index.php/Credits
8 * This program is free but copyrighted software; see
9 * the file COPYING for details.
11 * ---------------------------------------------------
15 #include "exitcodes.h"
16 #include "socketengines/socketengine_poll.h"
19 #include <sys/sysctl.h>
22 PollEngine::PollEngine(InspIRCd* Instance) : SocketEngine(Instance)
24 // Poll requires no special setup (which is nice).
28 ref = new EventHandler* [GetMaxFds()];
29 events = new struct pollfd[GetMaxFds()];
31 memset(events, 0, GetMaxFds() * sizeof(struct pollfd));
32 memset(ref, 0, GetMaxFds() * sizeof(EventHandler*));
35 PollEngine::~PollEngine()
37 // No destruction required, either.
42 bool PollEngine::AddFd(EventHandler* eh)
45 if ((fd < 0) || (fd > GetMaxFds() - 1))
47 ServerInstance->Logs->Log("SOCKET",DEBUG,"AddFd out of range: (fd: %d, max: %d)", fd, GetMaxFds());
51 if (GetRemainingFds() <= 1)
53 ServerInstance->Logs->Log("SOCKET",DEBUG,"No remaining FDs cannot add fd: %d", fd);
59 ServerInstance->Logs->Log("SOCKET",DEBUG,"Attempt to add duplicate fd: %d", fd);
67 events[fd].events = POLLIN;
71 events[fd].events = POLLOUT;
74 ServerInstance->Logs->Log("SOCKET", DEBUG,"New file descriptor: %d (%d)", fd, events[fd].events);
79 void PollEngine::WantWrite(EventHandler* eh)
81 events[eh->GetFd()].events = POLLIN | POLLOUT;
84 bool PollEngine::DelFd(EventHandler* eh, bool force)
87 if ((fd < 0) || (fd > MAX_DESCRIPTORS))
89 ServerInstance->Logs->Log("SOCKET", DEBUG, "DelFd out of range: (fd: %d, max: %d)", fd, GetMaxFds());
94 events[fd].events = 0;
99 ServerInstance->Logs->Log("SOCKET", DEBUG, "Remove file descriptor: %d", fd);
103 int PollEngine::GetMaxFds()
107 return MAX_DESCRIPTORS;
109 int max = ulimit(4, 0);
112 MAX_DESCRIPTORS = max;
118 ServerInstance->Logs->Log("SOCKET", DEFAULT, "ERROR: Can't determine maximum number of open sockets: %s", strerror(errno));
119 printf("ERROR: Can't determine maximum number of open sockets: %s\n", strerror(errno)));
120 ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
124 if (!MAX_DESCRIPTORS)
126 int mib[2], maxfiles;
130 mib[1] = KERN_MAXFILES;
131 len = sizeof(maxfiles);
132 sysctl(mib, 2, &maxfiles, &len, NULL, 0);
133 MAX_DESCRIPTORS = maxfiles;
136 return MAX_DESCRIPTORS;
140 int PollEngine::GetRemainingFds()
142 return MAX_DESCRIPTORS - CurrentSetSize;
145 int PollEngine::DispatchEvents()
147 int i = poll(events, GetMaxFds() - 1, 1000);
149 socklen_t codesize = sizeof(int);
155 for (fd = 0; fd < GetMaxFds() - 1 && processed != i; fd++)
157 if (events[fd].revents)
160 if (events[fd].revents & POLLHUP)
163 ref[fd]->HandleEvent(EVENT_ERROR, 0);
167 if (events[fd].revents & POLLERR)
170 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0)
173 ref[fd]->HandleEvent(EVENT_ERROR, errcode);
177 if (events[fd].revents & POLLOUT)
179 // Switch to wanting read again
180 // event handlers have to request to write again if they need it
181 events[fd].events = POLLIN;
185 ref[fd]->HandleEvent(EVENT_WRITE);
188 if (events[fd].revents & POLLIN)
191 ref[fd]->HandleEvent(EVENT_READ);
199 std::string PollEngine::GetName()