*/
-#include <iostream>
-#include <vector>
-#include <string>
-#include <map>
-#include "exitcodes.h"
#include "inspircd.h"
-#include "socketengine.h"
-
-#ifndef _WIN32
-# ifndef __USE_XOPEN
-# define __USE_XOPEN /* fuck every fucking OS ever made. needed by poll.h to work.*/
-# endif
-# include <poll.h>
-# include <sys/poll.h>
-# include <sys/resource.h>
-#else
-# define struct pollfd WSAPOLLFD
-# define poll WSAPoll
-#endif
+
+#include <sys/poll.h>
+#include <sys/resource.h>
/** A specialisation of the SocketEngine class, designed to use poll().
*/
-class PollEngine : public SocketEngine
+namespace
{
-private:
/** These are used by poll() to hold socket events
*/
- std::vector<struct pollfd> events;
+ std::vector<struct pollfd> events(16);
/** This vector maps fds to an index in the events array.
*/
- std::vector<int> fd_mappings;
-public:
- /** Create a new PollEngine
- */
- PollEngine();
- virtual bool AddFd(EventHandler* eh, int event_mask);
- virtual void OnSetEvent(EventHandler* eh, int old_mask, int new_mask);
- virtual void DelFd(EventHandler* eh);
- virtual int DispatchEvents();
- virtual std::string GetName();
-};
-
-PollEngine::PollEngine() : events(1), fd_mappings(1)
+ std::vector<int> fd_mappings(16, -1);
+}
+
+void SocketEngine::Init()
+{
+ LookupMaxFds();
+}
+
+void SocketEngine::Deinit()
+{
+}
+
+void SocketEngine::RecoverFromFork()
{
- CurrentSetSize = 0;
- struct rlimit limits;
- if (!getrlimit(RLIMIT_NOFILE, &limits))
- {
- MAX_DESCRIPTORS = limits.rlim_cur;
- }
- else
- {
- ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Can't determine maximum number of open sockets: %s", strerror(errno));
- std::cout << "ERROR: Can't determine maximum number of open sockets: " << strerror(errno) << std::endl;
- ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE);
- }
}
static int mask_to_poll(int event_mask)
return rv;
}
-bool PollEngine::AddFd(EventHandler* eh, int event_mask)
+bool SocketEngine::AddFd(EventHandler* eh, int event_mask)
{
int fd = eh->GetFd();
- if ((fd < 0) || (fd > GetMaxFds() - 1))
+ if (fd < 0)
{
- ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "AddFd out of range: (fd: %d, max: %d)", fd, GetMaxFds());
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "AddFd out of range: (fd: %d)", fd);
return false;
}
return false;
}
- if (!SocketEngine::AddFd(eh))
+ unsigned int index = CurrentSetSize;
+
+ if (!SocketEngine::AddFdRef(eh))
{
ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Attempt to add duplicate fd: %d", fd);
return false;
}
- unsigned int index = CurrentSetSize;
-
while (static_cast<unsigned int>(fd) >= fd_mappings.size())
fd_mappings.resize(fd_mappings.size() * 2, -1);
fd_mappings[fd] = index;
events[index].events = mask_to_poll(event_mask);
ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d (%d; index %d)", fd, events[index].events, index);
- SocketEngine::SetEventMask(eh, event_mask);
- CurrentSetSize++;
+ eh->SetEventMask(event_mask);
return true;
}
-void PollEngine::OnSetEvent(EventHandler* eh, int old_mask, int new_mask)
+void SocketEngine::OnSetEvent(EventHandler* eh, int old_mask, int new_mask)
{
int fd = eh->GetFd();
if (fd < 0 || static_cast<unsigned int>(fd) >= fd_mappings.size() || fd_mappings[fd] == -1)
events[fd_mappings[fd]].events = mask_to_poll(new_mask);
}
-void PollEngine::DelFd(EventHandler* eh)
+void SocketEngine::DelFd(EventHandler* eh)
{
int fd = eh->GetFd();
- if ((fd < 0) || (fd > MAX_DESCRIPTORS))
+ if (fd < 0)
{
- ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "DelFd out of range: (fd: %d, max: %d)", fd, GetMaxFds());
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "DelFd out of range: (fd: %d)", fd);
return;
}
events[last_index].fd = 0;
events[last_index].events = 0;
- SocketEngine::DelFd(eh);
-
- CurrentSetSize--;
+ SocketEngine::DelFdRef(eh);
ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Remove file descriptor: %d (index: %d) "
"(Filled gap with: %d (index: %d))", fd, index, last_fd, last_index);
}
-int PollEngine::DispatchEvents()
+int SocketEngine::DispatchEvents()
{
int i = poll(&events[0], CurrentSetSize, 1000);
- int index;
- socklen_t codesize = sizeof(int);
- int errcode;
int processed = 0;
ServerInstance->UpdateTime();
- for (index = 0; index < CurrentSetSize && processed < i; index++)
+ for (size_t index = 0; index < CurrentSetSize && processed < i; index++)
{
struct pollfd& pfd = events[index];
if (revents & POLLHUP)
{
- eh->HandleEvent(EVENT_ERROR, 0);
+ eh->OnEventHandlerError(0);
continue;
}
if (revents & POLLERR)
{
// Get error number
+ socklen_t codesize = sizeof(int);
+ int errcode;
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0)
errcode = errno;
- eh->HandleEvent(EVENT_ERROR, errcode);
+ eh->OnEventHandlerError(errcode);
continue;
}
if (revents & POLLIN)
{
- SetEventMask(eh, eh->GetEventMask() & ~FD_READ_WILL_BLOCK);
- eh->HandleEvent(EVENT_READ);
+ eh->SetEventMask(eh->GetEventMask() & ~FD_READ_WILL_BLOCK);
+ eh->OnEventHandlerRead();
if (eh != GetRef(fd))
// whoops, deleted out from under us
continue;
{
int mask = eh->GetEventMask();
mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE);
- SetEventMask(eh, mask);
+ eh->SetEventMask(mask);
// The vector could've been resized, reference can be invalid by now; don't use it
events[index].events = mask_to_poll(mask);
- eh->HandleEvent(EVENT_WRITE);
+ eh->OnEventHandlerWrite();
}
}
return i;
}
-
-std::string PollEngine::GetName()
-{
- return "poll";
-}
-
-SocketEngine* CreateSocketEngine()
-{
- return new PollEngine;
-}