153 lines
3.3 KiB
C
153 lines
3.3 KiB
C
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "fdevent.h"
|
|
#include "settings.h"
|
|
#include "buffer.h"
|
|
|
|
#ifdef USE_LINUX_EPOLL
|
|
static void fdevent_linux_sysepoll_free(fdevents *ev) {
|
|
close(ev->epoll_fd);
|
|
free(ev->epoll_events);
|
|
}
|
|
|
|
static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) {
|
|
struct epoll_event ep;
|
|
|
|
if (fde_ndx < 0) return -1;
|
|
|
|
memset(&ep, 0, sizeof(ep));
|
|
|
|
ep.data.fd = fd;
|
|
ep.data.ptr = NULL;
|
|
|
|
if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) {
|
|
fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
|
|
|
|
SEGFAULT();
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
return -1;
|
|
}
|
|
|
|
static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
|
|
struct epoll_event ep;
|
|
int add = 0;
|
|
|
|
if (fde_ndx == -1) add = 1;
|
|
|
|
memset(&ep, 0, sizeof(ep));
|
|
|
|
ep.events = 0;
|
|
|
|
if (events & FDEVENT_IN) ep.events |= EPOLLIN;
|
|
if (events & FDEVENT_OUT) ep.events |= EPOLLOUT;
|
|
|
|
ep.events |= EPOLLERR | EPOLLHUP | EPOLLET;
|
|
|
|
ep.data.ptr = NULL;
|
|
ep.data.fd = fd;
|
|
|
|
if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) {
|
|
fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
|
|
|
|
SEGFAULT();
|
|
|
|
return 0;
|
|
}
|
|
|
|
return fd;
|
|
}
|
|
|
|
static int fdevent_linux_sysepoll_poll(fdevents *ev, int timeout_ms) {
|
|
return epoll_wait(ev->epoll_fd, ev->epoll_events, ev->maxfds, timeout_ms);
|
|
}
|
|
|
|
static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) {
|
|
int events = 0, e;
|
|
|
|
e = ev->epoll_events[ndx].events;
|
|
if (e & EPOLLIN) events |= FDEVENT_IN;
|
|
if (e & EPOLLOUT) events |= FDEVENT_OUT;
|
|
if (e & EPOLLERR) events |= FDEVENT_ERR;
|
|
if (e & EPOLLHUP) events |= FDEVENT_HUP;
|
|
if (e & EPOLLPRI) events |= FDEVENT_PRI;
|
|
|
|
return e;
|
|
}
|
|
|
|
static int fdevent_linux_sysepoll_event_get_fd(fdevents *ev, size_t ndx) {
|
|
# if 0
|
|
fprintf(stderr, "%s.%d: %d, %d\n", __FILE__, __LINE__, ndx, ev->epoll_events[ndx].data.fd);
|
|
# endif
|
|
|
|
return ev->epoll_events[ndx].data.fd;
|
|
}
|
|
|
|
static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) {
|
|
size_t i;
|
|
|
|
UNUSED(ev);
|
|
|
|
i = (ndx < 0) ? 0 : ndx + 1;
|
|
|
|
return i;
|
|
}
|
|
|
|
int fdevent_linux_sysepoll_init(fdevents *ev) {
|
|
ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
|
|
#define SET(x) \
|
|
ev->x = fdevent_linux_sysepoll_##x;
|
|
|
|
SET(free);
|
|
SET(poll);
|
|
|
|
SET(event_del);
|
|
SET(event_add);
|
|
|
|
SET(event_next_fdndx);
|
|
SET(event_get_fd);
|
|
SET(event_get_revent);
|
|
|
|
if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) {
|
|
fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
|
|
__FILE__, __LINE__, strerror(errno));
|
|
|
|
return -1;
|
|
}
|
|
|
|
if (-1 == fcntl(ev->epoll_fd, F_SETFD, FD_CLOEXEC)) {
|
|
fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
|
|
__FILE__, __LINE__, strerror(errno));
|
|
|
|
close(ev->epoll_fd);
|
|
|
|
return -1;
|
|
}
|
|
|
|
ev->epoll_events = malloc(ev->maxfds * sizeof(*ev->epoll_events));
|
|
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
int fdevent_linux_sysepoll_init(fdevents *ev) {
|
|
UNUSED(ev);
|
|
|
|
fprintf(stderr, "%s.%d: linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
|
|
__FILE__, __LINE__);
|
|
|
|
return -1;
|
|
}
|
|
#endif
|