]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/socketengine_select.cpp
Tidy up strlens which are not required
[user/henk/code/inspircd.git] / src / socketengine_select.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 #include "inspircd.h"
18 #include <sys/select.h>
19 #include "socketengine_select.h"
20
21
22 SelectEngine::SelectEngine(InspIRCd* Instance) : SocketEngine(Instance)
23 {
24         ServerInstance->Log(DEBUG,"SelectEngine::SelectEngine()");
25         EngineHandle = 0;
26         CurrentSetSize = 0;
27 }
28
29 SelectEngine::~SelectEngine()
30 {
31         ServerInstance->Log(DEBUG,"SelectEngine::~SelectEngine()");
32 }
33
34 bool SelectEngine::AddFd(EventHandler* eh)
35 {
36         int fd = eh->GetFd();
37         if ((fd < 0) || (fd > MAX_DESCRIPTORS))
38         {
39                 ServerInstance->Log(DEFAULT,"ERROR: FD of %d added above max of %d",fd,MAX_DESCRIPTORS);
40                 return false;
41         }
42         if (GetRemainingFds() <= 1)
43         {
44                 ServerInstance->Log(DEFAULT,"ERROR: System out of file descriptors!");
45                 return false;
46         }
47
48         fds[fd] = fd;
49
50         if (ref[fd])
51                 return false;
52
53         ref[fd] = eh;
54         ServerInstance->Log(DEBUG,"Add socket %d",fd);
55
56         CurrentSetSize++;
57         return true;
58 }
59
60 bool SelectEngine::DelFd(EventHandler* eh)
61 {
62         int fd = eh->GetFd();
63
64         ServerInstance->Log(DEBUG,"SelectEngine::DelFd(%d)",fd);
65
66         if ((fd < 0) || (fd > MAX_DESCRIPTORS))
67                 return false;
68
69         std::map<int,int>::iterator t = fds.find(fd);
70         if (t != fds.end())
71         {
72                 fds.erase(t);
73                 ServerInstance->Log(DEBUG,"Deleted fd %d",fd);
74         }
75
76         CurrentSetSize--;
77         ref[fd] = NULL;
78         return true;
79 }
80
81 int SelectEngine::GetMaxFds()
82 {
83         return FD_SETSIZE;
84 }
85
86 int SelectEngine::GetRemainingFds()
87 {
88         return FD_SETSIZE - CurrentSetSize;
89 }
90
91 int SelectEngine::DispatchEvents()
92 {
93         int result = 0;
94         timeval tval;
95         int sresult = 0;
96         EventHandler* ev[MAX_DESCRIPTORS];
97
98         FD_ZERO(&wfdset);
99         FD_ZERO(&rfdset);
100
101         for (std::map<int,int>::iterator a = fds.begin(); a != fds.end(); a++)
102         {
103                 if (ref[a->second]->Readable())
104                 {
105                         FD_SET (a->second, &rfdset);
106                 }
107                 else
108                 {
109                         FD_SET (a->second, &wfdset);
110                 }
111                 
112         }
113         tval.tv_sec = 0;
114         tval.tv_usec = 50L;
115         sresult = select(FD_SETSIZE, &rfdset, &wfdset, NULL, &tval);
116         if (sresult > 0)
117         {
118                 for (std::map<int,int>::iterator a = fds.begin(); a != fds.end(); a++)
119                 {
120                         if ((FD_ISSET (a->second, &rfdset)) || (FD_ISSET (a->second, &wfdset)))
121                         {
122                                 ev[result++] = ref[a->second];
123                         }
124                 }
125         }
126
127         /** An event handler may remove its own descriptor from the list, therefore it is not
128          * safe to directly iterate over the list and dispatch events there with STL iterators.
129          * Thats a shame because it makes this code slower and more resource intensive, but maybe
130          * the user should stop using select(), as select() smells anyway.
131          */
132         for (int i = 0; i < result; i++)
133         {
134                 ServerInstance->Log(DEBUG,"Handle %s event on fd %d",ev[i]->Readable() ? "read" : "write", ev[i]->GetFd());
135                 ev[i]->HandleEvent(ev[i]->Readable() ? EVENT_READ : EVENT_WRITE);
136         }
137
138         return result;
139 }
140
141 std::string SelectEngine::GetName()
142 {
143         return "select";
144 }