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;
}
int SocketEngine::DispatchEvents()
{
	timeval tval;
	tval.tv_sec = 1;
	tval.tv_usec = 0;

	fd_set rfdset = ReadSet, wfdset = WriteSet, errfdset = ErrSet;

	int sresult = select(MaxFD + 1, &rfdset, &wfdset, &errfdset, &tval);
	ServerInstance->UpdateTime();

	for (int i = 0, j = sresult; i <= MaxFD && j > 0; i++)
	{
		int has_read = FD_ISSET(i, &rfdset), has_write = FD_ISSET(i, &wfdset), has_error = FD_ISSET(i, &errfdset);

		if (!(has_read || has_write || has_error))
			continue;

		--j;

		EventHandler* ev = GetRef(i);
		if (!ev)
			continue;

		if (has_error)
		{
			stats.ErrorEvents++;

			socklen_t codesize = sizeof(int);
			int errcode = 0;
			if (getsockopt(i, SOL_SOCKET, SO_ERROR, (char*)&errcode, &codesize) < 0)
				errcode = errno;

			ev->HandleEvent(EVENT_ERROR, errcode);
			continue;
		}

		if (has_read)
		{
			stats.ReadEvents++;
			ev->SetEventMask(ev->GetEventMask() & ~FD_READ_WILL_BLOCK);
			ev->HandleEvent(EVENT_READ);
			if (ev != GetRef(i))
				continue;
		}

		if (has_write)
		{
			stats.WriteEvents++;
			int newmask = (ev->GetEventMask() & ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE));
			SocketEngine::OnSetEvent(ev, ev->GetEventMask(), newmask);
			ev->SetEventMask(newmask);
			ev->HandleEvent(EVENT_WRITE);
		}
	}

	return sresult;
}
int PortsEngine::DispatchEvents()
{
	struct timespec poll_time;

	poll_time.tv_sec = 1;
	poll_time.tv_nsec = 0;

	unsigned int nget = 1; // used to denote a retrieve request.
	int ret = port_getn(EngineHandle, this->events, GetMaxFds() - 1, &nget, &poll_time);
	ServerInstance->UpdateTime();

	// first handle an error condition
	if (ret == -1)
		return -1;

	TotalEvents += nget;

	unsigned int i;
	for (i = 0; i < nget; i++)
	{
		switch (this->events[i].portev_source)
		{
			case PORT_SOURCE_FD:
			{
				int fd = this->events[i].portev_object;
				EventHandler* eh = ref[fd];
				if (eh)
				{
					int mask = eh->GetEventMask();
					if (events[i].portev_events & POLLWRNORM)
						mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE);
					if (events[i].portev_events & POLLRDNORM)
						mask &= ~FD_READ_WILL_BLOCK;
					// reinsert port for next time around, pretending to be one-shot for writes
					SetEventMask(eh, mask);
					port_associate(EngineHandle, PORT_SOURCE_FD, fd, mask_to_events(mask), eh);
					if (events[i].portev_events & POLLRDNORM)
					{
						ReadEvents++;
						eh->HandleEvent(EVENT_READ);
						if (eh != ref[fd])
							continue;
					}
					if (events[i].portev_events & POLLWRNORM)
					{
						WriteEvents++;
						eh->HandleEvent(EVENT_WRITE);
					}
				}
			}
			default:
			break;
		}
	}

	return (int)i;
}
int SelectEngine::DispatchEvents()
{
	static timeval tval = { 1, 0 };

	fd_set rfdset = ReadSet, wfdset = WriteSet, errfdset = ErrSet;

	int sresult = select(MaxFD + 1, &rfdset, &wfdset, &errfdset, &tval);
	ServerInstance->UpdateTime();

	/* Nothing to process this time around */
	if (sresult < 1)
		return 0;

	for (int i = 0, j = sresult; i <= MaxFD && j > 0; i++)
	{
		int has_read = FD_ISSET(i, &rfdset), has_write = FD_ISSET(i, &wfdset), has_error = FD_ISSET(i, &errfdset);

		if (has_read || has_write || has_error)
		{
			--j;

			EventHandler* ev = ref[i];
			if (!ev)
				continue;

			if (has_error)
			{
				ErrorEvents++;

				socklen_t codesize = sizeof(int);
				int errcode = 0;
				if (getsockopt(i, SOL_SOCKET, SO_ERROR, (char*)&errcode, &codesize) < 0)
					errcode = errno;

				ev->HandleEvent(EVENT_ERROR, errcode);
				continue;
			}

			if (has_read)
			{
				ReadEvents++;
				SetEventMask(ev, ev->GetEventMask() & ~FD_READ_WILL_BLOCK);
				ev->HandleEvent(EVENT_READ);
				if (ev != ref[i])
					continue;
			}
			if (has_write)
			{
				WriteEvents++;
				SetEventMask(ev, ev->GetEventMask() & ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE));
				ev->HandleEvent(EVENT_WRITE);
			}
		}
	}

	return sresult;
}
int KQueueEngine::DispatchEvents()
{
	ts.tv_nsec = 0;
	ts.tv_sec = 1;

	int i = kevent(EngineHandle, NULL, 0, &ke_list[0], ke_list.size(), &ts);
	ServerInstance->UpdateTime();

	if (i < 0)
		return i;

	TotalEvents += i;

	for (int j = 0; j < i; j++)
	{
		struct kevent& kev = ke_list[j];

		EventHandler* eh = GetRef(kev.ident);
		if (!eh)
			continue;

		if (kev.flags & EV_EOF)
		{
			ErrorEvents++;
			eh->HandleEvent(EVENT_ERROR, kev.fflags);
			continue;
		}
		if (kev.filter == EVFILT_WRITE)
		{
			WriteEvents++;
			/* When mask is FD_WANT_FAST_WRITE or FD_WANT_SINGLE_WRITE,
			 * we set a one-shot write, so we need to clear that bit
			 * to detect when it set again.
			 */
			const int bits_to_clr = FD_WANT_SINGLE_WRITE | FD_WANT_FAST_WRITE | FD_WRITE_WILL_BLOCK;
			SetEventMask(eh, eh->GetEventMask() & ~bits_to_clr);
			eh->HandleEvent(EVENT_WRITE);

			if (eh != GetRef(kev.ident))
				// whoops, deleted out from under us
				continue;
		}
		if (kev.filter == EVFILT_READ)
		{
			ReadEvents++;
			SetEventMask(eh, eh->GetEventMask() & ~FD_READ_WILL_BLOCK);
			eh->HandleEvent(EVENT_READ);
		}
	}

	return i;
}
Exemple #6
0
void SocketEngine::DispatchTrialWrites()
{
	std::vector<int> working_list;
	working_list.reserve(trials.size());
	working_list.assign(trials.begin(), trials.end());
	trials.clear();
	for(unsigned int i=0; i < working_list.size(); i++)
	{
		int fd = working_list[i];
		EventHandler* eh = GetRef(fd);
		if (!eh)
			continue;
		int mask = eh->event_mask;
		eh->event_mask &= ~(FD_ADD_TRIAL_READ | FD_ADD_TRIAL_WRITE);
		if ((mask & (FD_ADD_TRIAL_READ | FD_READ_WILL_BLOCK)) == FD_ADD_TRIAL_READ)
			eh->HandleEvent(EVENT_READ, 0);
		if ((mask & (FD_ADD_TRIAL_WRITE | FD_WRITE_WILL_BLOCK)) == FD_ADD_TRIAL_WRITE)
			eh->HandleEvent(EVENT_WRITE, 0);
	}
}
Exemple #7
0
int IOCPEngine::DispatchEvents()
{
	DWORD len;
	LPOVERLAPPED overlap;
	Overlapped * ov;
	EventHandler * eh;
	ULONG_PTR intfd;
	int ret;
	unsigned long bytes_recv;

	while (GetQueuedCompletionStatus(m_completionPort, &len, &intfd, &overlap, 1000))
	{
		if (intfd > (unsigned long)MAX_DESCRIPTORS)
			continue;

		// woot, we got an event on a socket :P
		eh = ref[intfd];
		ov = CONTAINING_RECORD(overlap, Overlapped, m_overlap);

		if (eh == 0)
			continue;

		void* m_readEvent = NULL;
		void* m_writeEvent = NULL;

		eh->GetExt("windows_readevent", m_readEvent);
		eh->GetExt("windows_writeevent", m_writeEvent);

		TotalEvents++;

		switch(ov->m_event)
		{
			case SOCKET_IO_EVENT_WRITE_READY:
			{
				WriteEvents++;
				eh->Shrink("windows_writeevent");
				eh->HandleEvent(EVENT_WRITE, 0);
			}
			break;

			case SOCKET_IO_EVENT_READ_READY:
			{
				ReadEvents++;
				if(ov->m_params)
				{
					// if we had params, it means we are a udp socket with a udp_overlap pointer in this long.
					udp_overlap * uv = (udp_overlap*)ov->m_params;
					uv->udp_len = len;
					this->udp_ov = uv;
					eh->Shrink("windows_readevent");
					eh->HandleEvent(EVENT_READ, 0);
					this->udp_ov = 0;
					delete uv;
					PostReadEvent(eh);
				}
				else
				{
					ret = ioctlsocket(eh->GetFd(), FIONREAD, &bytes_recv);
					eh->Shrink("windows_readevent");
					if(ret != 0 || bytes_recv == 0)
					{
						/* end of file */
						PostCompletionEvent(eh, SOCKET_IO_EVENT_ERROR, EIO); /* Old macdonald had an error, EIEIO. */
					}
					else
					{
						eh->HandleEvent(EVENT_READ, 0);
						PostReadEvent(eh);
					}
				}
			}
			break;

			case SOCKET_IO_EVENT_ACCEPT:
			{
				/* this is kinda messy.. :/ */
				ReadEvents++;
				eh->HandleEvent(EVENT_READ, ov->m_params);
				delete ((accept_overlap*)ov->m_params);
				eh->Shrink("windows_acceptevent");
				PostAcceptEvent(eh);
			}
			break;

			case SOCKET_IO_EVENT_ERROR:
			{
				ErrorEvents++;
				eh->HandleEvent(EVENT_ERROR, ov->m_params);
			}
			break;
		}

		delete ov;
	}

	return 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 = 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;
}