Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

socketengine.cpp

Go to the documentation of this file.
00001 /*       +------------------------------------+
00002  *       | Inspire Internet Relay Chat Daemon |
00003  *       +------------------------------------+
00004  *
00005  *  Inspire is copyright (C) 2002-2005 ChatSpike-Dev.
00006  *                       E-mail:
00007  *                <brain@chatspike.net>
00008  *                <Craig@chatspike.net>
00009  *
00010  * Written by Craig Edwards, Craig McLure, and others.
00011  * This program is free but copyrighted software; see
00012  *            the file COPYING for details.
00013  *
00014  * ---------------------------------------------------
00015  */
00016 
00017 #include "inspircd_config.h"
00018 #include "globals.h"
00019 #include "inspircd.h"
00020 #ifdef USE_EPOLL
00021 #include <sys/epoll.h>
00022 #define EP_DELAY 5
00023 #endif
00024 #ifdef USE_KQUEUE
00025 #include <sys/types.h>
00026 #include <sys/event.h>
00027 #include <sys/time.h>
00028 #endif
00029 #include <vector>
00030 #include <string>
00031 #include "socketengine.h"
00032 
00033 char ref[65535];
00034 
00035 SocketEngine::SocketEngine()
00036 {
00037         log(DEBUG,"SocketEngine::SocketEngine()");
00038 #ifdef USE_EPOLL
00039         EngineHandle = epoll_create(65535);
00040 #endif
00041 #ifdef USE_KQUEUE
00042         EngineHandle = kqueue();
00043 #endif
00044 }
00045 
00046 SocketEngine::~SocketEngine()
00047 {
00048         log(DEBUG,"SocketEngine::~SocketEngine()");
00049 #ifdef USE_EPOLL
00050         close(EngineHandle);
00051 #endif
00052 #ifdef USE_KQUEUE
00053         close(EngineHandle);
00054 #endif
00055 }
00056 
00057 char SocketEngine::GetType(int fd)
00058 {
00059         if ((fd < 0) || (fd > 65535))
00060                 return X_EMPTY_SLOT;
00061         /* Mask off the top bit used for 'read/write' state */
00062         return (ref[fd] & ~0x80);
00063 }
00064 
00065 bool SocketEngine::AddFd(int fd, bool readable, char type)
00066 {
00067         if ((fd < 0) || (fd > 65535))
00068                 return false;
00069         this->fds.push_back(fd);
00070         ref[fd] = type;
00071         if (readable)
00072         {
00073                 log(DEBUG,"Set readbit");
00074                 ref[fd] |= X_READBIT;
00075         }
00076         log(DEBUG,"Add socket %d",fd);
00077 #ifdef USE_EPOLL
00078         struct epoll_event ev;
00079         log(DEBUG,"epoll: Add socket to events, ep=%d socket=%d",EngineHandle,fd);
00080         readable ? ev.events = EPOLLIN | EPOLLET : ev.events = EPOLLOUT | EPOLLET;
00081         ev.data.fd = fd;
00082         int i = epoll_ctl(EngineHandle, EPOLL_CTL_ADD, fd, &ev);
00083         if (i < 0)
00084         {
00085                 log(DEBUG,"epoll: List insertion failure!");
00086                 return false;
00087         }
00088 #endif
00089 #ifdef USE_KQUEUE
00090         struct kevent ke;
00091         log(DEBUG,"kqueue: Add socket to events, kq=%d socket=%d",EngineHandle,fd);
00092         EV_SET(&ke, fd, readable ? EVFILT_READ : EVFILT_WRITE, EV_ADD, 0, 0, NULL);
00093         int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
00094         if (i == -1)
00095         {
00096                 log(DEBUG,"kqueue: List insertion failure!");
00097                 return false;
00098         }
00099 #endif
00100 return true;
00101 }
00102 
00103 bool SocketEngine::DelFd(int fd)
00104 {
00105         log(DEBUG,"SocketEngine::DelFd(%d)",fd);
00106 
00107         if ((fd < 0) || (fd > 65535))
00108                 return false;
00109 
00110         bool found = false;
00111         for (std::vector<int>::iterator i = fds.begin(); i != fds.end(); i++)
00112         {
00113                 if (*i == fd)
00114                 {
00115                         fds.erase(i);
00116                         log(DEBUG,"Deleted fd %d",fd);
00117                         found = true;
00118                         break;
00119                 }
00120         }
00121 #ifdef USE_KQUEUE
00122         struct kevent ke;
00123         EV_SET(&ke, fd, ref[fd] && X_READBIT ? EVFILT_READ : EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
00124         int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
00125         if (i == -1)
00126         {
00127                 log(DEBUG,"kqueue: Failed to remove socket from queue!");
00128                 return false;
00129         }
00130 #endif
00131 #ifdef USE_EPOLL
00132         struct epoll_event ev;
00133         ref[fd] && X_READBIT ? ev.events = EPOLLIN | EPOLLET : ev.events = EPOLLOUT | EPOLLET;
00134         ev.data.fd = fd;
00135         int i = epoll_ctl(EngineHandle, EPOLL_CTL_DEL, fd, &ev);
00136         if (i < 0)
00137         {
00138                 log(DEBUG,"epoll: List deletion failure!");
00139                 return false;
00140         }
00141 #endif
00142         ref[fd] = 0;
00143         return found;
00144 }
00145 
00146 bool SocketEngine::Wait(std::vector<int> &fdlist)
00147 {
00148         fdlist.clear();
00149 #ifdef USE_SELECT
00150         FD_ZERO(&wfdset);
00151         FD_ZERO(&rfdset);
00152         timeval tval;
00153         int sresult;
00154         for (unsigned int a = 0; a < fds.size(); a++)
00155         {
00156                 if (ref[fds[a]] & X_READBIT)
00157                 {
00158                         FD_SET (fds[a], &rfdset);
00159                 }
00160                 else
00161                 {
00162                         FD_SET (fds[a], &wfdset);
00163                 }
00164                 
00165         }
00166         tval.tv_sec = 0;
00167         tval.tv_usec = 1000L;
00168         sresult = select(FD_SETSIZE, &rfdset, &wfdset, NULL, &tval);
00169         if (sresult > 0)
00170         {
00171                 for (unsigned int a = 0; a < fds.size(); a++)
00172                 {
00173                         if ((FD_ISSET (fds[a], &rfdset)) || (FD_ISSET (fds[a], &wfdset)))
00174                         {
00175                                 log(DEBUG,"...Adding active %d",fds[a]);
00176                                 fdlist.push_back(fds[a]);
00177                         }
00178                 }
00179         }
00180 #endif
00181 #ifdef USE_KQUEUE
00182         ts.tv_nsec = 1000L;
00183         ts.tv_sec = 0;
00184         int i = kevent(EngineHandle, NULL, 0, &ke_list[0], 65535, &ts);
00185         for (int j = 0; j < i; j++)
00186                 fdlist.push_back(ke_list[j].ident);
00187 #endif
00188 #ifdef USE_EPOLL
00189         int i = epoll_wait(EngineHandle, events, 65535, 1);
00190         for (int j = 0; j < i; j++)
00191                 fdlist.push_back(events[j].data.fd);
00192 #endif
00193         return true;
00194 }
00195 
00196 std::string SocketEngine::GetName()
00197 {
00198 #ifdef USE_SELECT
00199         return "select";
00200 #endif
00201 #ifdef USE_KQUEUE
00202         return "kqueue";
00203 #endif
00204 #ifdef USE_EPOLL
00205         return "epoll";
00206 #endif
00207         return "misconfigured";
00208 }

Generated on Mon Dec 12 13:31:08 2005 for InspIRCd by  doxygen 1.4.4-20050815