]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/socketengine_select.cpp
Store id in TreeServer, use TreeServer::GetID() to get the id (NOTE: it is std::string)
[user/henk/code/inspircd.git] / src / socketengine_select.cpp
index 73e909193b597deb9c0d882576d485bf932621c1..b87d2769d6dd969b275995b8758ac1a8388e9ed7 100644 (file)
@@ -1 +1,166 @@
-/*       +------------------------------------+\r *       | Inspire Internet Relay Chat Daemon |\r *       +------------------------------------+\r *\r *  InspIRCd: (C) 2002-2007 InspIRCd Development Team\r * See: http://www.inspircd.org/wiki/index.php/Credits\r *\r * This program is free but copyrighted software; see\r *            the file COPYING for details.\r *\r * ---------------------------------------------------\r */\r\r#include "inspircd.h"\r#include <sys/select.h>\r#include "socketengine_select.h"\r\r\rSelectEngine::SelectEngine(InspIRCd* Instance) : SocketEngine(Instance)\r{\r        EngineHandle = 0;\r      CurrentSetSize = 0;\r    memset(writeable, 0, sizeof(writeable));\r}\r\rSelectEngine::~SelectEngine()\r{\r}\r\rbool SelectEngine::AddFd(EventHandler* eh)\r{\r    int fd = eh->GetFd();\r  if ((fd < 0) || (fd > MAX_DESCRIPTORS))\r                return false;\r\r if (GetRemainingFds() <= 1)\r            return false;\r\r fds[fd] = fd;\r\r if (ref[fd])\r           return false;\r\r ref[fd] = eh;\r\r CurrentSetSize++;\r\r     ServerInstance->Log(DEBUG,"New file descriptor: %d", fd);\r      return true;\r}\r\rvoid SelectEngine::WantWrite(EventHandler* eh)\r{\r       writeable[eh->GetFd()] = true;\r}\r\rbool SelectEngine::DelFd(EventHandler* eh, bool force)\r{\r     int fd = eh->GetFd();\r\r if ((fd < 0) || (fd > MAX_DESCRIPTORS))\r                return false;\r\r std::map<int,int>::iterator t = fds.find(fd);\r  if (t != fds.end())\r            fds.erase(t);\r\r CurrentSetSize--;\r      ref[fd] = NULL;\r\r       ServerInstance->Log(DEBUG,"Remove file descriptor: %d", fd);\r   return true;\r}\r\rint SelectEngine::GetMaxFds()\r{\r        return FD_SETSIZE;\r}\r\rint SelectEngine::GetRemainingFds()\r{\r    return FD_SETSIZE - CurrentSetSize;\r}\r\rint SelectEngine::DispatchEvents()\r{\r    int result = 0;\r        timeval tval;\r  int sresult = 0;\r       EventHandler* ev[MAX_DESCRIPTORS];\r     socklen_t codesize;\r    int errcode;\r\r  FD_ZERO(&wfdset);\r      FD_ZERO(&rfdset);\r      FD_ZERO(&errfdset);\r\r   for (std::map<int,int>::iterator a = fds.begin(); a != fds.end(); a++)\r {\r              if (ref[a->second]->Readable())\r                        FD_SET (a->second, &rfdset);\r           else\r                   FD_SET (a->second, &wfdset);\r           if (writeable[a->second])\r                      FD_SET (a->second, &wfdset);\r\r          FD_SET (a->second, &errfdset);\r }\r      tval.tv_sec = 1;\r       tval.tv_usec = 0;\r      sresult = select(FD_SETSIZE, &rfdset, &wfdset, &errfdset, &tval);\r      if (sresult > 0)\r       {\r              for (std::map<int,int>::iterator a = fds.begin(); a != fds.end(); a++)\r         {\r                      if ((FD_ISSET (a->second, &rfdset)) || (FD_ISSET (a->second, &wfdset)) || FD_ISSET (a->second, &errfdset))\r                     {\r                              ev[result++] = ref[a->second];\r                 }\r              }\r      }\r\r     /** An event handler may remove its own descriptor from the list, therefore it is not\r   * safe to directly iterate over the list and dispatch events there with STL iterators.\r         * Thats a shame because it makes this code slower and more resource intensive, but maybe\r       * the user should stop using select(), as select() smells anyway.\r      */\r    for (int i = 0; i < result; i++)\r       {\r              if (ev[i])\r             {\r                      if (FD_ISSET (ev[i]->GetFd(), &errfdset))\r                      {\r                              if (ev[i])\r                             {\r                                      if (getsockopt(ev[i]->GetFd(), SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0)\r                                         errcode = errno;\r\r                                      ev[i]->HandleEvent(EVENT_ERROR, errcode);\r                              }\r                              continue;\r                      }\r                      if (ev[i])\r                     {\r                              if (writeable[ev[i]->GetFd()])\r                         {\r                                      if (ev[i])\r                                             ev[i]->HandleEvent(EVENT_WRITE);\r                                       writeable[ev[i]->GetFd()] = false;\r\r                            }\r                              else\r                           {\r                                      if (ev[i])\r                                             ev[i]->HandleEvent(ev[i]->Readable() ? EVENT_READ : EVENT_WRITE);\r                              }\r                      }\r              }\r      }\r\r     return result;\r}\r\rstd::string SelectEngine::GetName()\r{\r        return "select";\r}\r
\ No newline at end of file
+/*       +------------------------------------+
+ *       | Inspire Internet Relay Chat Daemon |
+ *       +------------------------------------+
+ *
+ *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ *            the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include <sys/select.h>
+#include "socketengine_select.h"
+
+
+SelectEngine::SelectEngine(InspIRCd* Instance) : SocketEngine(Instance)
+{
+       EngineHandle = 0;
+       CurrentSetSize = 0;
+       memset(writeable, 0, sizeof(writeable));
+}
+
+SelectEngine::~SelectEngine()
+{
+}
+
+bool SelectEngine::AddFd(EventHandler* eh)
+{
+       int fd = eh->GetFd();
+       if ((fd < 0) || (fd > MAX_DESCRIPTORS))
+               return false;
+
+       if (GetRemainingFds() <= 1)
+               return false;
+
+       fds[fd] = fd;
+
+       if (ref[fd])
+               return false;
+
+       ref[fd] = eh;
+
+       CurrentSetSize++;
+
+       ServerInstance->Log(DEBUG,"New file descriptor: %d", fd);
+       return true;
+}
+
+void SelectEngine::WantWrite(EventHandler* eh)
+{
+       writeable[eh->GetFd()] = true;
+}
+
+bool SelectEngine::DelFd(EventHandler* eh, bool force)
+{
+       int fd = eh->GetFd();
+
+       if ((fd < 0) || (fd > MAX_DESCRIPTORS))
+               return false;
+
+       std::map<int,int>::iterator t = fds.find(fd);
+       if (t != fds.end())
+               fds.erase(t);
+
+       CurrentSetSize--;
+       ref[fd] = NULL;
+
+       ServerInstance->Log(DEBUG,"Remove file descriptor: %d", fd);
+       return true;
+}
+
+int SelectEngine::GetMaxFds()
+{
+       return FD_SETSIZE;
+}
+
+int SelectEngine::GetRemainingFds()
+{
+       return FD_SETSIZE - CurrentSetSize;
+}
+
+int SelectEngine::DispatchEvents()
+{
+       int result = 0;
+       timeval tval;
+       int sresult = 0;
+       EventHandler* ev[MAX_DESCRIPTORS];
+       socklen_t codesize;
+       int errcode;
+
+       FD_ZERO(&wfdset);
+       FD_ZERO(&rfdset);
+       FD_ZERO(&errfdset);
+
+       for (std::map<int,int>::iterator a = fds.begin(); a != fds.end(); a++)
+       {
+               if (ref[a->second]->Readable())
+                       FD_SET (a->second, &rfdset);
+               else
+                       FD_SET (a->second, &wfdset);
+               if (writeable[a->second])
+                       FD_SET (a->second, &wfdset);
+
+               FD_SET (a->second, &errfdset);
+       }
+       tval.tv_sec = 1;
+       tval.tv_usec = 0;
+       sresult = select(FD_SETSIZE, &rfdset, &wfdset, &errfdset, &tval);
+       if (sresult > 0)
+       {
+               for (std::map<int,int>::iterator a = fds.begin(); a != fds.end(); a++)
+               {
+                       if ((FD_ISSET (a->second, &rfdset)) || (FD_ISSET (a->second, &wfdset)) || FD_ISSET (a->second, &errfdset))
+                       {
+                               ev[result++] = ref[a->second];
+                       }
+               }
+       }
+
+       /** An event handler may remove its own descriptor from the list, therefore it is not
+        * safe to directly iterate over the list and dispatch events there with STL iterators.
+        * Thats a shame because it makes this code slower and more resource intensive, but maybe
+        * the user should stop using select(), as select() smells anyway.
+        */
+       for (int i = 0; i < result; i++)
+       {
+               if (ev[i])
+               {
+                       if (FD_ISSET (ev[i]->GetFd(), &errfdset))
+                       {
+                               if (ev[i])
+                               {
+                                       if (getsockopt(ev[i]->GetFd(), SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0)
+                                               errcode = errno;
+
+                                       ev[i]->HandleEvent(EVENT_ERROR, errcode);
+                               }
+                               continue;
+                       }
+                       if (ev[i])
+                       {
+                               if (writeable[ev[i]->GetFd()])
+                               {
+                                       writeable[ev[i]->GetFd()] = false;
+                                       if (ev[i])
+                                               ev[i]->HandleEvent(EVENT_WRITE);
+                               }
+                               else
+                               {
+                                       if (ev[i])
+                                               ev[i]->HandleEvent(ev[i]->Readable() ? EVENT_READ : EVENT_WRITE);
+                               }
+                       }
+               }
+       }
+
+       return result;
+}
+
+std::string SelectEngine::GetName()
+{
+       return "select";
+}