1#include "base.h" 2#include "log.h" 3 4#include <sys/types.h> 5 6#include <unistd.h> 7#include <stdlib.h> 8#include <string.h> 9#include <errno.h> 10#include <stdio.h> 11#include <fcntl.h> 12#include <assert.h> 13 14 15fdevents *fdevent_init(server *srv, size_t maxfds, fdevent_handler_t type) { 16 fdevents *ev; 17 18 ev = calloc(1, sizeof(*ev)); 19 ev->srv = srv; 20 ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray)); 21 ev->maxfds = maxfds; 22 23 switch(type) { 24 case FDEVENT_HANDLER_POLL: 25 if (0 != fdevent_poll_init(ev)) { 26 log_error_write(srv, __FILE__, __LINE__, "S", 27 "event-handler poll failed"); 28 goto error; 29 } 30 return ev; 31 case FDEVENT_HANDLER_SELECT: 32 if (0 != fdevent_select_init(ev)) { 33 log_error_write(srv, __FILE__, __LINE__, "S", 34 "event-handler select failed"); 35 goto error; 36 } 37 return ev; 38 case FDEVENT_HANDLER_LINUX_SYSEPOLL: 39 if (0 != fdevent_linux_sysepoll_init(ev)) { 40 log_error_write(srv, __FILE__, __LINE__, "S", 41 "event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\""); 42 goto error; 43 } 44 return ev; 45 case FDEVENT_HANDLER_SOLARIS_DEVPOLL: 46 if (0 != fdevent_solaris_devpoll_init(ev)) { 47 log_error_write(srv, __FILE__, __LINE__, "S", 48 "event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\""); 49 goto error; 50 } 51 return ev; 52 case FDEVENT_HANDLER_SOLARIS_PORT: 53 if (0 != fdevent_solaris_port_init(ev)) { 54 log_error_write(srv, __FILE__, __LINE__, "S", 55 "event-handler solaris-eventports failed, try to set server.event-handler = \"poll\" or \"select\""); 56 goto error; 57 } 58 return ev; 59 case FDEVENT_HANDLER_FREEBSD_KQUEUE: 60 if (0 != fdevent_freebsd_kqueue_init(ev)) { 61 log_error_write(srv, __FILE__, __LINE__, "S", 62 "event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\""); 63 goto error; 64 } 65 return ev; 66 case FDEVENT_HANDLER_LIBEV: 67 if (0 != fdevent_libev_init(ev)) { 68 log_error_write(srv, __FILE__, __LINE__, "S", 69 "event-handler libev failed, try to set server.event-handler = \"poll\" or \"select\""); 70 goto error; 71 } 72 return ev; 73 case FDEVENT_HANDLER_UNSET: 74 break; 75 } 76 77error: 78 free(ev->fdarray); 79 free(ev); 80 81 log_error_write(srv, __FILE__, __LINE__, "S", 82 "event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\""); 83 return NULL; 84} 85 86void fdevent_free(fdevents *ev) { 87 size_t i; 88 if (!ev) return; 89 90 if (ev->free) ev->free(ev); 91 92 for (i = 0; i < ev->maxfds; i++) { 93 if (ev->fdarray[i]) free(ev->fdarray[i]); 94 } 95 96 free(ev->fdarray); 97 free(ev); 98} 99 100int fdevent_reset(fdevents *ev) { 101 if (ev->reset) return ev->reset(ev); 102 103 return 0; 104} 105 106static fdnode *fdnode_init(void) { 107 fdnode *fdn; 108 109 fdn = calloc(1, sizeof(*fdn)); 110 fdn->fd = -1; 111 return fdn; 112} 113 114static void fdnode_free(fdnode *fdn) { 115 free(fdn); 116} 117 118int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) { 119 fdnode *fdn; 120 121 fdn = fdnode_init(); 122 fdn->handler = handler; 123 fdn->fd = fd; 124 fdn->ctx = ctx; 125 fdn->handler_ctx = NULL; 126 fdn->events = 0; 127 128 ev->fdarray[fd] = fdn; 129 130 return 0; 131} 132 133int fdevent_unregister(fdevents *ev, int fd) { 134 fdnode *fdn; 135 136 if (!ev) return 0; 137 fdn = ev->fdarray[fd]; 138 139 force_assert(fdn->events == 0); 140 141 fdnode_free(fdn); 142 143 ev->fdarray[fd] = NULL; 144 145 return 0; 146} 147 148int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) { 149 int fde = fde_ndx ? *fde_ndx : -1; 150 151 if (NULL == ev->fdarray[fd]) return 0; 152 153 if (ev->event_del) fde = ev->event_del(ev, fde, fd); 154 ev->fdarray[fd]->events = 0; 155 156 if (fde_ndx) *fde_ndx = fde; 157 158 return 0; 159} 160 161int fdevent_event_set(fdevents *ev, int *fde_ndx, int fd, int events) { 162 int fde = fde_ndx ? *fde_ndx : -1; 163 164 if (ev->event_set) fde = ev->event_set(ev, fde, fd, events); 165 ev->fdarray[fd]->events = events; 166 167 if (fde_ndx) *fde_ndx = fde; 168 169 return 0; 170} 171 172int fdevent_poll(fdevents *ev, int timeout_ms) { 173 if (ev->poll == NULL) SEGFAULT(); 174 return ev->poll(ev, timeout_ms); 175} 176 177int fdevent_event_get_revent(fdevents *ev, size_t ndx) { 178 if (ev->event_get_revent == NULL) SEGFAULT(); 179 180 return ev->event_get_revent(ev, ndx); 181} 182 183int fdevent_event_get_fd(fdevents *ev, size_t ndx) { 184 if (ev->event_get_fd == NULL) SEGFAULT(); 185 186 return ev->event_get_fd(ev, ndx); 187} 188 189fdevent_handler fdevent_get_handler(fdevents *ev, int fd) { 190 if (ev->fdarray[fd] == NULL) SEGFAULT(); 191 if (ev->fdarray[fd]->fd != fd) SEGFAULT(); 192 193 return ev->fdarray[fd]->handler; 194} 195 196void * fdevent_get_context(fdevents *ev, int fd) { 197 if (ev->fdarray[fd] == NULL) SEGFAULT(); 198 if (ev->fdarray[fd]->fd != fd) SEGFAULT(); 199 200 return ev->fdarray[fd]->ctx; 201} 202 203void fd_close_on_exec(int fd) { 204#ifdef FD_CLOEXEC 205 if (fd < 0) return; 206 force_assert(-1 != fcntl(fd, F_SETFD, FD_CLOEXEC)); 207#else 208 UNUSED(fd); 209#endif 210} 211 212int fdevent_fcntl_set(fdevents *ev, int fd) { 213 fd_close_on_exec(fd); 214 if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd); 215#ifdef O_NONBLOCK 216 return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR); 217#else 218 return 0; 219#endif 220} 221 222 223int fdevent_event_next_fdndx(fdevents *ev, int ndx) { 224 if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx); 225 226 return -1; 227} 228 229