bool SocketEngine::AddFd(EventHandler* eh, int event_mask) { int fd = eh->GetFd(); if ((fd < 0) || (fd > GetMaxFds() - 1)) { ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "AddFd out of range: (fd: %d, max: %d)", fd, GetMaxFds()); return false; } if (static_cast<unsigned int>(fd) < fd_mappings.size() && fd_mappings[fd] != -1) { ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Attempt to add duplicate fd: %d", fd); return false; } unsigned int index = CurrentSetSize; if (!SocketEngine::AddFdRef(eh)) { ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Attempt to add duplicate fd: %d", fd); return false; } while (static_cast<unsigned int>(fd) >= fd_mappings.size()) fd_mappings.resize(fd_mappings.size() * 2, -1); fd_mappings[fd] = index; ResizeDouble(events); events[index].fd = fd; 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); eh->SetEventMask(event_mask); return true; }
bool PollEngine::AddFd(EventHandler* eh, int event_mask) { int fd = eh->GetFd(); if ((fd < 0) || (fd > GetMaxFds() - 1)) { ServerInstance->Logs->Log("SOCKET",DEBUG,"AddFd out of range: (fd: %d, max: %d)", fd, GetMaxFds()); return false; } if (fd_mappings.find(fd) != fd_mappings.end()) { ServerInstance->Logs->Log("SOCKET",DEBUG,"Attempt to add duplicate fd: %d", fd); return false; } unsigned int index = CurrentSetSize; fd_mappings[fd] = index; ref[index] = eh; events[index].fd = fd; events[index].events = mask_to_poll(event_mask); ServerInstance->Logs->Log("SOCKET", DEBUG,"New file descriptor: %d (%d; index %d)", fd, events[index].events, index); SocketEngine::SetEventMask(eh, event_mask); CurrentSetSize++; return true; }
int PollEngine::DispatchEvents() { int i = poll(events, CurrentSetSize, 1000); int index; socklen_t codesize = sizeof(int); int errcode; int processed = 0; ServerInstance->UpdateTime(); if (i > 0) { for (index = 0; index < CurrentSetSize && processed != i; index++) { if (events[index].revents) processed++; EventHandler* eh = ref[index]; if (!eh) continue; if (events[index].revents & POLLHUP) { eh->HandleEvent(EVENT_ERROR, 0); continue; } if (events[index].revents & POLLERR) { // Get fd int fd = events[index].fd; // Get error number if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0) errcode = errno; eh->HandleEvent(EVENT_ERROR, errcode); continue; } if (events[index].revents & POLLIN) { SetEventMask(eh, eh->GetEventMask() & ~FD_READ_WILL_BLOCK); eh->HandleEvent(EVENT_READ); if (eh != ref[index]) // whoops, deleted out from under us continue; } if (events[index].revents & POLLOUT) { int mask = eh->GetEventMask(); mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE); SetEventMask(eh, mask); events[index].events = mask_to_poll(mask); eh->HandleEvent(EVENT_WRITE); } } } return i; }
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) { ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "SetEvents() on unknown fd: %d", eh->GetFd()); return; } events[fd_mappings[fd]].events = mask_to_poll(new_mask); }
void PollEngine::OnSetEvent(EventHandler* eh, int old_mask, int new_mask) { std::map<int, unsigned int>::iterator it = fd_mappings.find(eh->GetFd()); if (it == fd_mappings.end()) { ServerInstance->Logs->Log("SOCKET",DEBUG,"SetEvents() on unknown fd: %d", eh->GetFd()); return; } events[it->second].events = mask_to_poll(new_mask); }
int SocketEngine::DispatchEvents() { int i = poll(&events[0], CurrentSetSize, 1000); int processed = 0; ServerInstance->UpdateTime(); for (int index = 0; index < CurrentSetSize && processed < i; index++) { struct pollfd& pfd = events[index]; // Copy these in case the vector gets resized and pfd invalidated const int fd = pfd.fd; const short revents = pfd.revents; if (revents) processed++; EventHandler* eh = GetRef(fd); if (!eh) continue; if (revents & POLLHUP) { eh->HandleEvent(EVENT_ERROR, 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); continue; } if (revents & POLLIN) { eh->SetEventMask(eh->GetEventMask() & ~FD_READ_WILL_BLOCK); eh->HandleEvent(EVENT_READ); if (eh != GetRef(fd)) // whoops, deleted out from under us continue; } if (revents & POLLOUT) { int mask = eh->GetEventMask(); mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE); 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); } } return i; }