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