bool KQueueEngine::AddFd(EventHandler* eh, int event_mask)
{
	int fd = eh->GetFd();

	if ((fd < 0) || (fd > GetMaxFds() - 1))
		return false;

	if (ref[fd])
		return false;

	// We always want to read from the socket...
	struct kevent ke;
	EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);

	int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
	if (i == -1)
	{
		ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "Failed to add fd: %d %s",
					  fd, strerror(errno));
		return false;
	}

	ref[fd] = eh;
	SocketEngine::SetEventMask(eh, event_mask);
	OnSetEvent(eh, 0, event_mask);
	CurrentSetSize++;

	ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d", fd);
	return true;
}
bool SocketEngine::AddFd(EventHandler* eh, int event_mask)
{
	int fd = eh->GetFd();
	if ((fd < 0) || (fd > GetMaxFds() - 1))
		return false;

	if (!SocketEngine::AddFdRef(eh))
		return false;

	eh->SetEventMask(event_mask);
	OnSetEvent(eh, 0, event_mask);
	FD_SET(fd, &ErrSet);
	if (fd > MaxFD)
		MaxFD = fd;

	ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d", fd);
	return true;
}
Example #3
0
void SocketEngine::ChangeEventMask(EventHandler* eh, int change)
{
	int old_m = eh->event_mask;
	int new_m = old_m;

	// if we are changing read/write type, remove the previously set bit
	if (change & FD_WANT_READ_MASK)
		new_m &= ~FD_WANT_READ_MASK;
	if (change & FD_WANT_WRITE_MASK)
		new_m &= ~FD_WANT_WRITE_MASK;

	// if adding a trial read/write, insert it into the set
	if (change & FD_TRIAL_NOTE_MASK && !(old_m & FD_TRIAL_NOTE_MASK))
		trials.insert(eh->GetFd());

	new_m |= change;
	if (new_m == old_m)
		return;

	eh->event_mask = new_m;
	OnSetEvent(eh, old_m, new_m);
}
Example #4
0
int EPollEngine::DispatchEvents()
{
	socklen_t codesize = sizeof(int);
	int errcode;
	int i = epoll_wait(EngineHandle, events, GetMaxFds() - 1, 1000);
	ServerInstance->UpdateTime();

	TotalEvents += i;

	for (int j = 0; j < i; j++)
	{
		EventHandler* eh = ref[events[j].data.fd];
		if (!eh)
		{
			ServerInstance->Logs->Log("SOCKET",LOG_DEBUG,"Got event on unknown fd: %d", events[j].data.fd);
			epoll_ctl(EngineHandle, EPOLL_CTL_DEL, events[j].data.fd, &events[j]);
			continue;
		}
		if (events[j].events & EPOLLHUP)
		{
			ErrorEvents++;
			eh->HandleEvent(EVENT_ERROR, 0);
			continue;
		}
		if (events[j].events & EPOLLERR)
		{
			ErrorEvents++;
			/* Get error number */
			if (getsockopt(events[j].data.fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0)
				errcode = errno;
			eh->HandleEvent(EVENT_ERROR, errcode);
			continue;
		}
		int mask = eh->GetEventMask();
		if (events[j].events & EPOLLIN)
			mask &= ~FD_READ_WILL_BLOCK;
		if (events[j].events & EPOLLOUT)
		{
			mask &= ~FD_WRITE_WILL_BLOCK;
			if (mask & FD_WANT_SINGLE_WRITE)
			{
				int nm = mask & ~FD_WANT_SINGLE_WRITE;
				OnSetEvent(eh, mask, nm);
				mask = nm;
			}
		}
		SetEventMask(eh, mask);
		if (events[j].events & EPOLLIN)
		{
			ReadEvents++;
			eh->HandleEvent(EVENT_READ);
			if (eh != ref[events[j].data.fd])
				// whoa! we got deleted, better not give out the write event
				continue;
		}
		if (events[j].events & EPOLLOUT)
		{
			WriteEvents++;
			eh->HandleEvent(EVENT_WRITE);
		}
	}

	return i;
}
int SocketEngine::DispatchEvents()
{
	int i = epoll_wait(EngineHandle, &events[0], events.size(), 1000);
	ServerInstance->UpdateTime();

	stats.TotalEvents += i;

	for (int j = 0; j < i; j++)
	{
		// Copy these in case the vector gets resized and ev invalidated
		const epoll_event ev = events[j];

		EventHandler* const eh = static_cast<EventHandler*>(ev.data.ptr);
		const int fd = eh->GetFd();
		if (fd < 0)
			continue;

		if (ev.events & EPOLLHUP)
		{
			stats.ErrorEvents++;
			eh->OnEventHandlerError(0);
			continue;
		}

		if (ev.events & EPOLLERR)
		{
			stats.ErrorEvents++;
			/* Get error number */
			socklen_t codesize = sizeof(int);
			int errcode;
			if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0)
				errcode = errno;
			eh->OnEventHandlerError(errcode);
			continue;
		}

		int mask = eh->GetEventMask();
		if (ev.events & EPOLLIN)
			mask &= ~FD_READ_WILL_BLOCK;
		if (ev.events & EPOLLOUT)
		{
			mask &= ~FD_WRITE_WILL_BLOCK;
			if (mask & FD_WANT_SINGLE_WRITE)
			{
				int nm = mask & ~FD_WANT_SINGLE_WRITE;
				OnSetEvent(eh, mask, nm);
				mask = nm;
			}
		}
		eh->SetEventMask(mask);
		if (ev.events & EPOLLIN)
		{
			stats.ReadEvents++;
			eh->OnEventHandlerRead();
			if (eh != GetRef(fd))
				// whoa! we got deleted, better not give out the write event
				continue;
		}
		if (ev.events & EPOLLOUT)
		{
			stats.WriteEvents++;
			eh->OnEventHandlerWrite();
		}
	}

	return i;
}