]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/socketengines/socketengine_ports.cpp
d23857f506d500293e7311dd61d17bfc3ee000da
[user/henk/code/inspircd.git] / src / socketengines / socketengine_ports.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
6  * See: http://wiki.inspircd.org/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 <port.h>
17 #include "socketengines/socketengine_ports.h"
18 #include <ulimit.h>
19
20 PortsEngine::PortsEngine()
21 {
22         int max = ulimit(4, 0);
23         if (max > 0)
24         {
25                 MAX_DESCRIPTORS = max;
26                 return max;
27         }
28         else
29         {
30                 ServerInstance->Logs->Log("SOCKET", DEFAULT, "ERROR: Can't determine maximum number of open sockets!");
31                 printf("ERROR: Can't determine maximum number of open sockets!\n");
32                 ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
33         }
34         EngineHandle = port_create();
35
36         if (EngineHandle == -1)
37         {
38                 ServerInstance->Logs->Log("SOCKET",SPARSE,"ERROR: Could not initialize socket engine: %s", strerror(errno));
39                 ServerInstance->Logs->Log("SOCKET",SPARSE,"ERROR: This is a fatal error, exiting now.");
40                 printf("ERROR: Could not initialize socket engine: %s\n", strerror(errno));
41                 printf("ERROR: This is a fatal error, exiting now.\n");
42                 ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
43         }
44         CurrentSetSize = 0;
45
46         ref = new EventHandler* [GetMaxFds()];
47         events = new port_event_t[GetMaxFds()];
48         memset(ref, 0, GetMaxFds() * sizeof(EventHandler*));
49 }
50
51 PortsEngine::~PortsEngine()
52 {
53         this->Close(EngineHandle);
54         delete[] ref;
55         delete[] events;
56 }
57
58 static int mask_to_events(int event_mask)
59 {
60         int rv = 0;
61         if (event_mask & (FD_WANT_POLL_READ | FD_WANT_FAST_READ))
62                 rv |= POLLRDNORM;
63         if (event_mask & (FD_WANT_POLL_WRITE | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE))
64                 rv |= POLLWRNORM;
65         return rv;
66 }
67
68 bool PortsEngine::AddFd(EventHandler* eh, int event_mask)
69 {
70         int fd = eh->GetFd();
71         if ((fd < 0) || (fd > GetMaxFds() - 1))
72                 return false;
73
74         if (ref[fd])
75                 return false;
76
77         ref[fd] = eh;
78         SocketEngine::SetEventMask(eh, event_mask);
79         port_associate(EngineHandle, PORT_SOURCE_FD, fd, mask_to_events(event_mask), eh);
80
81         ServerInstance->Logs->Log("SOCKET",DEBUG,"New file descriptor: %d", fd);
82         CurrentSetSize++;
83         return true;
84 }
85
86 void PortsEngine::WantWrite(EventHandler* eh, int old_mask, int new_mask)
87 {
88         if (mask_to_events(new_mask) != mask_to_events(old_mask))
89                 port_associate(EngineHandle, PORT_SOURCE_FD, eh->GetFd(), mask_to_events(new_mask), eh);
90 }
91
92 bool PortsEngine::DelFd(EventHandler* eh, bool force)
93 {
94         int fd = eh->GetFd();
95         if ((fd < 0) || (fd > GetMaxFds() - 1))
96                 return false;
97
98         port_dissociate(EngineHandle, PORT_SOURCE_FD, fd);
99
100         CurrentSetSize--;
101         ref[fd] = NULL;
102
103         ServerInstance->Logs->Log("SOCKET",DEBUG,"Remove file descriptor: %d", fd);
104         return true;
105 }
106
107 int PortsEngine::DispatchEvents()
108 {
109         struct timespec poll_time;
110
111         poll_time.tv_sec = 1;
112         poll_time.tv_nsec = 0;
113
114         unsigned int nget = 1; // used to denote a retrieve request.
115         int i = port_getn(EngineHandle, this->events, GetMaxFds() - 1, &nget, &poll_time);
116
117         // first handle an error condition
118         if (i == -1)
119                 return i;
120
121         TotalEvents += nget;
122
123         for (i = 0; i < nget; i++)
124         {
125                 switch (this->events[i].portev_source)
126                 {
127                         case PORT_SOURCE_FD:
128                         {
129                                 int fd = this->events[i].portev_object;
130                                 EventHandler* eh = ref[fd];
131                                 if (eh)
132                                 {
133                                         int mask = eh->GetEventMask();
134                                         if (events[i].portev_events & POLLWRNORM)
135                                                 mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE);
136                                         if (events[i].portev_events & POLLRDNORM)
137                                                 mask &= ~FD_READ_WILL_BLOCK;
138                                         // reinsert port for next time around, pretending to be one-shot for writes
139                                         SetEventMask(ev, mask);
140                                         port_associate(EngineHandle, PORT_SOURCE_FD, fd, mask_to_events(mask), eh);
141                                         if (events[i].portev_events & POLLRDNORM)
142                                         {
143                                                 ReadEvents++;
144                                                 eh->HandleEvent(EVENT_READ);
145                                         }
146                                         if (events[i].portev_events & POLLWRNORM)
147                                         {
148                                                 WriteEvents++;
149                                                 eh->HandleEvent(EVENT_WRITE);
150                                         }
151                                 }
152                         }
153                         default:
154                         break;
155                 }
156         }
157
158         return i;
159 }
160
161 std::string PortsEngine::GetName()
162 {
163         return "ports";
164 }
165