1#include "fdevent.h" 2#include "buffer.h" 3#include "log.h" 4 5#include <sys/types.h> 6 7#include <unistd.h> 8#include <stdlib.h> 9#include <stdio.h> 10#include <string.h> 11#include <errno.h> 12#include <signal.h> 13#include <fcntl.h> 14 15#ifdef USE_POLL 16 17# ifdef HAVE_POLL_H 18# include <poll.h> 19# else 20# include <sys/poll.h> 21# endif 22 23static void fdevent_poll_free(fdevents *ev) { 24 free(ev->pollfds); 25 if (ev->unused.ptr) free(ev->unused.ptr); 26} 27 28static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) { 29 if (fde_ndx < 0) return -1; 30 31 if ((size_t)fde_ndx >= ev->used) { 32 log_error_write(ev->srv, __FILE__, __LINE__, "SdD", 33 "del! out of range ", fde_ndx, (int) ev->used); 34 SEGFAULT(); 35 } 36 37 if (ev->pollfds[fde_ndx].fd == fd) { 38 size_t k = fde_ndx; 39 40 ev->pollfds[k].fd = -1; 41 /* ev->pollfds[k].events = 0; */ 42 /* ev->pollfds[k].revents = 0; */ 43 44 if (ev->unused.size == 0) { 45 ev->unused.size = 16; 46 ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size); 47 } else if (ev->unused.size == ev->unused.used) { 48 ev->unused.size += 16; 49 ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size); 50 } 51 52 ev->unused.ptr[ev->unused.used++] = k; 53 } else { 54 log_error_write(ev->srv, __FILE__, __LINE__, "SdD", 55 "del! ", ev->pollfds[fde_ndx].fd, fd); 56 57 SEGFAULT(); 58 } 59 60 return -1; 61} 62 63#if 0 64static int fdevent_poll_event_compress(fdevents *ev) { 65 size_t j; 66 67 if (ev->used == 0) return 0; 68 if (ev->unused.used != 0) return 0; 69 70 for (j = ev->used - 1; j + 1 > 0 && ev->pollfds[j].fd == -1; j--) ev->used--; 71 72 return 0; 73} 74#endif 75 76static int fdevent_poll_event_set(fdevents *ev, int fde_ndx, int fd, int events) { 77 int pevents = 0; 78 if (events & FDEVENT_IN) pevents |= POLLIN; 79 if (events & FDEVENT_OUT) pevents |= POLLOUT; 80 81 /* known index */ 82 83 if (fde_ndx != -1) { 84 if (ev->pollfds[fde_ndx].fd == fd) { 85 ev->pollfds[fde_ndx].events = pevents; 86 87 return fde_ndx; 88 } 89 log_error_write(ev->srv, __FILE__, __LINE__, "SdD", 90 "set: ", fde_ndx, ev->pollfds[fde_ndx].fd); 91 SEGFAULT(); 92 } 93 94 if (ev->unused.used > 0) { 95 int k = ev->unused.ptr[--ev->unused.used]; 96 97 ev->pollfds[k].fd = fd; 98 ev->pollfds[k].events = pevents; 99 100 return k; 101 } else { 102 if (ev->size == 0) { 103 ev->size = 16; 104 ev->pollfds = malloc(sizeof(*ev->pollfds) * ev->size); 105 } else if (ev->size == ev->used) { 106 ev->size += 16; 107 ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size); 108 } 109 110 ev->pollfds[ev->used].fd = fd; 111 ev->pollfds[ev->used].events = pevents; 112 113 return ev->used++; 114 } 115} 116 117static int fdevent_poll_poll(fdevents *ev, int timeout_ms) { 118#if 0 119 fdevent_poll_event_compress(ev); 120#endif 121 return poll(ev->pollfds, ev->used, timeout_ms); 122} 123 124static int fdevent_poll_event_get_revent(fdevents *ev, size_t ndx) { 125 int r, poll_r; 126 127 if (ndx >= ev->used) { 128 log_error_write(ev->srv, __FILE__, __LINE__, "sii", 129 "dying because: event: ", (int) ndx, (int) ev->used); 130 131 SEGFAULT(); 132 133 return 0; 134 } 135 136 if (ev->pollfds[ndx].revents & POLLNVAL) { 137 /* should never happen */ 138 SEGFAULT(); 139 } 140 141 r = 0; 142 poll_r = ev->pollfds[ndx].revents; 143 144 /* map POLL* to FDEVEN_*; they are probably the same, but still. */ 145 146 if (poll_r & POLLIN) r |= FDEVENT_IN; 147 if (poll_r & POLLOUT) r |= FDEVENT_OUT; 148 if (poll_r & POLLERR) r |= FDEVENT_ERR; 149 if (poll_r & POLLHUP) r |= FDEVENT_HUP; 150 if (poll_r & POLLNVAL) r |= FDEVENT_NVAL; 151 if (poll_r & POLLPRI) r |= FDEVENT_PRI; 152 153 return r; 154} 155 156static int fdevent_poll_event_get_fd(fdevents *ev, size_t ndx) { 157 return ev->pollfds[ndx].fd; 158} 159 160static int fdevent_poll_event_next_fdndx(fdevents *ev, int ndx) { 161 size_t i; 162 163 i = (ndx < 0) ? 0 : ndx + 1; 164 for (; i < ev->used; i++) { 165 if (ev->pollfds[i].revents) return i; 166 } 167 168 return -1; 169} 170 171int fdevent_poll_init(fdevents *ev) { 172 ev->type = FDEVENT_HANDLER_POLL; 173#define SET(x) \ 174 ev->x = fdevent_poll_##x; 175 176 SET(free); 177 SET(poll); 178 179 SET(event_del); 180 SET(event_set); 181 182 SET(event_next_fdndx); 183 SET(event_get_fd); 184 SET(event_get_revent); 185 186 return 0; 187} 188 189 190 191 192#else 193int fdevent_poll_init(fdevents *ev) { 194 UNUSED(ev); 195 196 log_error_write(srv, __FILE__, __LINE__, 197 "s", "poll is not supported, try to set server.event-handler = \"select\""); 198 199 return -1; 200} 201#endif 202