]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/socketengines/socketengine_poll.cpp
Fix my massacre of kqueue, filters may not be or'd.
[user/henk/code/inspircd.git] / src / socketengines / socketengine_poll.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
6  * See: http://www.inspircd.org/wiki/index.php/Credits
7  *
8  * This program is free but copyrighted software; see
9  *            the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 #include "inspircd.h"
15 #include "exitcodes.h"
16 #include "socketengines/socketengine_poll.h"
17 #include <ulimit.h>
18
19 PollEngine::PollEngine(InspIRCd* Instance) : SocketEngine(Instance)
20 {
21         // Poll requires no special setup (which is nice).
22         CurrentSetSize = 0;
23         MAX_DESCRIPTORS = 0;
24
25         ref = new EventHandler* [GetMaxFds()];
26         events = new struct pollfd[GetMaxFds()];
27
28         memset(events, 0, GetMaxFds() * sizeof(struct pollfd));
29         memset(ref, 0, GetMaxFds() * sizeof(EventHandler*));
30 }
31
32 PollEngine::~PollEngine()
33 {
34         // No destruction required, either.
35         delete[] ref;
36         delete[] events;
37 }
38
39 bool PollEngine::AddFd(EventHandler* eh)
40 {
41         int fd = eh->GetFd();
42         if ((fd < 0) || (fd > GetMaxFds() - 1))
43         {
44                 ServerInstance->Logs->Log("SOCKET",DEBUG,"AddFd out of range: (fd: %d, max: %d)", fd, GetMaxFds());
45                 return false;
46         }
47
48         if (GetRemainingFds() <= 1)
49         {
50                 ServerInstance->Logs->Log("SOCKET",DEBUG,"No remaining FDs cannot add fd: %d", fd);
51                 return false;
52         }
53
54         if (ref[fd])
55         {
56                 ServerInstance->Logs->Log("SOCKET",DEBUG,"Attempt to add duplicate fd: %d", fd);
57                 return false;
58         }
59
60         ref[fd] = eh;
61         events[fd].fd = fd;
62         if (eh->Readable())
63         {
64                 events[fd].events = POLLIN;
65         }
66         else
67         {
68                 events[fd].events = POLLOUT;
69         }
70
71         ServerInstance->Logs->Log("SOCKET", DEBUG,"New file descriptor: %d (%d)", fd, events[fd].events);
72         CurrentSetSize++;
73         return true;
74 }
75
76 void PollEngine::WantWrite(EventHandler* eh)
77 {
78         events[eh->GetFd()].events = POLLIN | POLLOUT;
79 }
80
81 bool PollEngine::DelFd(EventHandler* eh, bool force)
82 {
83         int fd = eh->GetFd();
84         if ((fd < 0) || (fd > MAX_DESCRIPTORS))
85         {
86                 ServerInstance->Logs->Log("SOCKET", DEBUG, "DelFd out of range: (fd: %d, max: %d)", fd, GetMaxFds());
87                 return false;
88         }
89
90         events[fd].fd = -1;
91         events[fd].events = 0;
92
93         CurrentSetSize--;
94         ref[fd] = NULL;
95
96         ServerInstance->Logs->Log("SOCKET", DEBUG, "Remove file descriptor: %d", fd);
97         return true;
98 }
99
100 int PollEngine::GetMaxFds()
101 {
102         if (MAX_DESCRIPTORS)
103                 return MAX_DESCRIPTORS;
104
105         int max = ulimit(4, 0);
106         if (max > 0)
107         {
108                 MAX_DESCRIPTORS = max;
109                 return max;
110         }
111         else
112         {
113                 ServerInstance->Logs->Log("SOCKET", DEFAULT, "ERROR: Can't determine maximum number of open sockets!");
114                 printf("ERROR: Can't determine maximum number of open sockets!\n");
115                 ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
116         }
117         return 0;
118 }
119
120 int PollEngine::GetRemainingFds()
121 {
122         return MAX_DESCRIPTORS - CurrentSetSize;
123 }
124
125 int PollEngine::DispatchEvents()
126 {
127         int i = poll(events, GetMaxFds() - 1, 1000);
128         int fd = 0;
129         socklen_t codesize = sizeof(int);
130         int errcode;
131         int processed = 0;
132
133         if (i > 0)
134         {
135                 for (fd = 0; fd < GetMaxFds() - 1 && processed != i; fd++)
136                 {
137                         if (events[fd].revents)
138                                 processed++;
139
140                         if (events[fd].revents & POLLHUP)
141                         {
142                                 if (ref[fd])
143                                         ref[fd]->HandleEvent(EVENT_ERROR, 0);
144                                 continue;
145                         }
146
147                         if (events[fd].revents & POLLERR)
148                         {
149                                 // Get error number
150                                 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0)
151                                         errcode = errno;
152                                 if (ref[fd])
153                                         ref[fd]->HandleEvent(EVENT_ERROR, errcode);
154                                 continue;
155                         }
156
157                         if (events[fd].revents & POLLOUT)
158                         {
159                                 // Switch to wanting read again
160                                 // event handlers have to request to write again if they need it
161                                 events[fd].events = POLLIN;
162
163
164                                 if (ref[fd])
165                                         ref[fd]->HandleEvent(EVENT_WRITE);
166                         }
167
168                         if (events[fd].revents & POLLIN)
169                         {
170                                 if (ref[fd])
171                                         ref[fd]->HandleEvent(EVENT_READ);
172                         }
173                 }
174         }
175
176         return i;
177 }
178
179 std::string PollEngine::GetName()
180 {
181         return "poll";
182 }
183