/************************************************************************
* IRC - Internet Relay Chat, src/socketengine_devpoll.c
* Copyright (C) 2004 David Parton
*
* engine functions for the /dev/poll socket engine
*
*/
/* $Id: socketengine_devpoll.c,v 1.1.1.1 2005/06/27 03:02:35 sheik Exp $ */
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "h.h"
#include "fds.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/devpoll.h>
#include <sys/poll.h>
static int devpoll_id = -1, numfds = 0;
void engine_init()
{
devpoll_id = open("/dev/poll", O_RDWR);
}
void engine_add_fd(int fd)
{
struct pollfd dev_fd;
if (numfds >= MAXCONNECTIONS)
abort();
dev_fd.events = 0;
dev_fd.revents = 0;
dev_fd.fd = fd;
if (write(devpoll_id, &dev_fd, sizeof(struct pollfd)) != sizeof(struct pollfd))
abort();
set_fd_internal(fd, 0);
++numfds;
}
void engine_del_fd(int fd)
{
struct pollfd dev_fd;
dev_fd.events = POLLREMOVE;
dev_fd.revents = 0;
dev_fd.fd = fd;
if (write(devpoll_id, &dev_fd, sizeof(struct pollfd)) != sizeof(struct pollfd))
abort();
--numfds;
}
void engine_change_fd_state(int fd, unsigned int stateplus)
{
unsigned int events = 0;
struct pollfd dev_fd;
if (stateplus & FDF_WANTWRITE) events |= POLLOUT;
if (stateplus & FDF_WANTREAD) events |= POLLIN|POLLHUP|POLLERR;
dev_fd.events = events;
dev_fd.revents = 0;
dev_fd.fd = fd;
if (write(devpoll_id, &dev_fd, sizeof(struct pollfd)) != sizeof(struct pollfd))
abort();
set_fd_internal(fd, (void*)events);
}
#define ENGINE_MAX_EVENTS 512
#define ENGINE_MAX_LOOPS (2 * (MAXCONNECTIONS / 512))
int engine_read_message(time_t delay)
{
struct pollfd events[ENGINE_MAX_EVENTS], *pevent;
struct dvpoll dopoll;
int nfds, i, numloops = 0, eventsfull;
unsigned int fdflags, fdevents;
int fdtype;
void *fdvalue;
aClient *cptr;
aListener *lptr;
dopoll.dp_fds = events;
dopoll.dp_nfds = ENGINE_MAX_EVENTS;
dopoll.dp_timeout = delay;
do
{
nfds = ioctl(devpoll_id, DP_POLL, &dopoll);
if (nfds < 0)
{
if (errno == EINTR || errno == EAGAIN)
return -1;
report_error("ioctl(devpoll): %s:%s", &me);
sleep(5);
return -1;
}
eventsfull = nfds == ENGINE_MAX_EVENTS;
if (delay || numloops)
NOW = timeofday = time(NULL);
numloops++;
for (i = 0, pevent = events; i < nfds; i++, pevent++)
{
fdevents = (unsigned int)get_fd_internal(pevent->fd);
if (pevent->fd != -1)
{
int rr = (pevent->revents & (POLLIN|POLLHUP|POLLERR)) && (fdevents & (POLLIN|POLLHUP|POLLERR));
int rw = (pevent->revents & POLLOUT) && (fdevents & POLLOUT);
get_fd_info(pevent->fd, &fdtype, &fdflags, &fdvalue);
switch (fdtype)
{
case FDT_NONE:
break;
case FDT_AUTH:
cptr = (aClient*)fdvalue;
if (rr) read_authports(cptr);
if (rw && cptr->authfd >= 0) send_authports(cptr);
check_client_fd(cptr);
break;
case FDT_LISTENER:
lptr = (aListener*)fdvalue;
if (rr) accept_connection(lptr);
break;
case FDT_RESOLVER:
do_dns_async();
break;
case FDT_CLIENT:
cptr = (aClient*)fdvalue;
readwrite_client(cptr, rr, rw);
break;
case FDT_CALLBACKP:
{
struct fd_callbackp *fdcb = (struct fd_callbackp*)fdvalue;
fdcb->rdf = rr;
fdcb->wrf = rw;
(*fdcb->callback)(fdcb);
break;
}
default:
abort();
}
}
}
} while (eventsfull && numloops < ENGINE_MAX_LOOPS);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1