X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/a51e573de1800142f3573b3c973879ee351f1a3d..ec4de7f8c59e136f02451f4adfbe87b6d7ef36af:/fake_epoll.h diff --git a/fake_epoll.h b/fake_epoll.h new file mode 100644 index 0000000..d89f86a --- /dev/null +++ b/fake_epoll.h @@ -0,0 +1,179 @@ +/* kludge up some limited epoll semantics using select for 2.4 kernels */ +/* $Id: fake_epoll.h,v 1.1 2005/06/04 15:42:35 bodea Exp $ */ + +#ifndef __FAKE_EPOLL_H__ +#define __FAKE_EPOLL_H__ + +#define EPOLLIN 0x01 +#define EPOLLOUT 0x04 +#define EPOLLERR 0x08 +#define EPOLLHUP 0x10 + +#define EPOLL_CTL_ADD 1 +#define EPOLL_CTL_DEL 2 +#define EPOLL_CTL_MOD 3 + +struct epoll_event { + uint32_t events; + union epoll_data { + void *ptr; + int fd; + uint32_t u32; + uint64_t u64; + } data; +}; + +int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); + +#ifdef FAKE_EPOLL_IMPLEMENTATION + +#include + +static fd_set _epoll_read_set; +static fd_set _epoll_write_set; +static int _epoll_fds; +static struct epoll_event *_epoll_data[128]; + +static int epoll_create(int size __attribute__ ((unused))) +{ + static int once = 0; + if (once++) + { + errno = ENFILE; /* only support one instance */ + return -1; + } + + FD_ZERO(&_epoll_read_set); + FD_ZERO(&_epoll_write_set); + _epoll_fds = 0; + + memset(_epoll_data, 0, sizeof(_epoll_data)); + + return 1; /* "descriptor" */ +} + +int epoll_ctl(int epfd __attribute__ ((unused)), int op, int fd, + struct epoll_event *event) +{ + if (fd > (sizeof(_epoll_data)/sizeof(*_epoll_data)) - 1) + { + errno = EINVAL; + return -1; + } + + switch (op) + { + case EPOLL_CTL_ADD: + if (event->events & EPOLLIN) + FD_SET(fd, &_epoll_read_set); + + if (event->events & EPOLLOUT) + FD_SET(fd, &_epoll_write_set); + + if (fd >= _epoll_fds) + _epoll_fds = fd + 1; + + if (_epoll_data[fd]) + free(_epoll_data[fd]); + + if (!(_epoll_data[fd] = malloc(sizeof(*_epoll_data)))) + { + errno = ENOMEM; + return -1; + } + + memcpy(_epoll_data[fd], &event->data, sizeof(*_epoll_data)); + break; + + case EPOLL_CTL_MOD: + if (event->events & EPOLLIN) + FD_SET(fd, &_epoll_read_set); + else + FD_CLR(fd, &_epoll_read_set); + + if (event->events & EPOLLOUT) + FD_SET(fd, &_epoll_write_set); + else + FD_CLR(fd, &_epoll_write_set); + + memcpy(_epoll_data[fd], &event->data, sizeof(*_epoll_data)); + break; + + case EPOLL_CTL_DEL: + FD_CLR(fd, &_epoll_read_set); + FD_CLR(fd, &_epoll_write_set); + + free(_epoll_data[fd]); + _epoll_data[fd] = 0; + + if (fd == _epoll_fds - 1) + { + _epoll_fds = 0; + while (fd-- > 0) + { + if (FD_ISSET(fd, &_epoll_read_set) || + FD_ISSET(fd, &_epoll_write_set)) + { + _epoll_fds = fd + 1; + break; + } + } + } + + break; + } + + return 0; +} + +static int epoll_wait(int epfd __attribute__ ((unused)), + struct epoll_event *events, int maxevents, int timout) +{ + fd_set r; + fd_set w; + struct timeval t; + struct timeval *tp; + int n; + int e; + int i; + + memcpy(&r, &_epoll_read_set, sizeof(r)); + memcpy(&w, &_epoll_write_set, sizeof(w)); + + if (timout >= 0) + { + t.tv_sec = 0; + t.tv_usec = timout * 1000; + tp = &t; + } + else + tp = 0; + + n = select(_epoll_fds, &r, &w, 0, tp); + if (n > maxevents) + n = maxevents; + + for (i = e = 0; n > 0 && i < _epoll_fds; i++) + { + if (!_epoll_data[i]) + continue; + + events[e].events = 0; + if (FD_ISSET(i, &r)) + events[e].events |= EPOLLIN; + + if (FD_ISSET(i, &w)) + events[e].events |= EPOLLOUT; + + if (events[e].events) + { + memcpy(&events[e++].data, _epoll_data[i], sizeof(events[0].data)); + n--; + } + } + + return e; +} + +#endif /* FAKE_EPOLL_IMPLEMENTATION */ +#endif /* __FAKE_EPOLL_H__ */