[core] http_response_send_file() shared code (#2017)
[lighttpd.git] / src / fdevent.c
blob82b71ce6921c8c4a71f696ae23a64c03ac333692
1 #include "first.h"
3 #include "base.h"
4 #include "log.h"
6 #include <sys/types.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <stdio.h>
13 #include <fcntl.h>
14 #include <assert.h>
17 fdevents *fdevent_init(server *srv, size_t maxfds, fdevent_handler_t type) {
18 fdevents *ev;
20 ev = calloc(1, sizeof(*ev));
21 force_assert(NULL != ev);
22 ev->srv = srv;
23 ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
24 force_assert(NULL != ev->fdarray);
25 ev->maxfds = maxfds;
27 switch(type) {
28 case FDEVENT_HANDLER_POLL:
29 if (0 != fdevent_poll_init(ev)) {
30 log_error_write(srv, __FILE__, __LINE__, "S",
31 "event-handler poll failed");
32 goto error;
34 return ev;
35 case FDEVENT_HANDLER_SELECT:
36 if (0 != fdevent_select_init(ev)) {
37 log_error_write(srv, __FILE__, __LINE__, "S",
38 "event-handler select failed");
39 goto error;
41 return ev;
42 case FDEVENT_HANDLER_LINUX_SYSEPOLL:
43 if (0 != fdevent_linux_sysepoll_init(ev)) {
44 log_error_write(srv, __FILE__, __LINE__, "S",
45 "event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"");
46 goto error;
48 return ev;
49 case FDEVENT_HANDLER_SOLARIS_DEVPOLL:
50 if (0 != fdevent_solaris_devpoll_init(ev)) {
51 log_error_write(srv, __FILE__, __LINE__, "S",
52 "event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"");
53 goto error;
55 return ev;
56 case FDEVENT_HANDLER_SOLARIS_PORT:
57 if (0 != fdevent_solaris_port_init(ev)) {
58 log_error_write(srv, __FILE__, __LINE__, "S",
59 "event-handler solaris-eventports failed, try to set server.event-handler = \"poll\" or \"select\"");
60 goto error;
62 return ev;
63 case FDEVENT_HANDLER_FREEBSD_KQUEUE:
64 if (0 != fdevent_freebsd_kqueue_init(ev)) {
65 log_error_write(srv, __FILE__, __LINE__, "S",
66 "event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"");
67 goto error;
69 return ev;
70 case FDEVENT_HANDLER_LIBEV:
71 if (0 != fdevent_libev_init(ev)) {
72 log_error_write(srv, __FILE__, __LINE__, "S",
73 "event-handler libev failed, try to set server.event-handler = \"poll\" or \"select\"");
74 goto error;
76 return ev;
77 case FDEVENT_HANDLER_UNSET:
78 break;
81 error:
82 free(ev->fdarray);
83 free(ev);
85 log_error_write(srv, __FILE__, __LINE__, "S",
86 "event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"");
87 return NULL;
90 void fdevent_free(fdevents *ev) {
91 size_t i;
92 if (!ev) return;
94 if (ev->free) ev->free(ev);
96 for (i = 0; i < ev->maxfds; i++) {
97 if (ev->fdarray[i]) free(ev->fdarray[i]);
100 free(ev->fdarray);
101 free(ev);
104 int fdevent_reset(fdevents *ev) {
105 if (ev->reset) return ev->reset(ev);
107 return 0;
110 static fdnode *fdnode_init(void) {
111 fdnode *fdn;
113 fdn = calloc(1, sizeof(*fdn));
114 force_assert(NULL != fdn);
115 fdn->fd = -1;
116 return fdn;
119 static void fdnode_free(fdnode *fdn) {
120 free(fdn);
123 int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
124 fdnode *fdn;
126 fdn = fdnode_init();
127 fdn->handler = handler;
128 fdn->fd = fd;
129 fdn->ctx = ctx;
130 fdn->handler_ctx = NULL;
131 fdn->events = 0;
133 ev->fdarray[fd] = fdn;
135 return 0;
138 int fdevent_unregister(fdevents *ev, int fd) {
139 fdnode *fdn;
141 if (!ev) return 0;
142 fdn = ev->fdarray[fd];
144 force_assert(fdn->events == 0);
146 fdnode_free(fdn);
148 ev->fdarray[fd] = NULL;
150 return 0;
153 void fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
154 if (-1 == fd) return;
155 if (NULL == ev->fdarray[fd]) return;
157 if (ev->event_del) *fde_ndx = ev->event_del(ev, *fde_ndx, fd);
158 ev->fdarray[fd]->events = 0;
161 void fdevent_event_set(fdevents *ev, int *fde_ndx, int fd, int events) {
162 if (-1 == fd) return;
164 /*(Note: skips registering with kernel if initial events is 0,
165 * so caller should pass non-zero events for initial registration.
166 * If never registered due to never being called with non-zero events,
167 * then FDEVENT_HUP or FDEVENT_ERR will never be returned.) */
168 if (ev->fdarray[fd]->events == events) return;/*(no change; nothing to do)*/
170 if (ev->event_set) *fde_ndx = ev->event_set(ev, *fde_ndx, fd, events);
171 ev->fdarray[fd]->events = events;
174 int fdevent_poll(fdevents *ev, int timeout_ms) {
175 if (ev->poll == NULL) SEGFAULT();
176 return ev->poll(ev, timeout_ms);
179 int fdevent_event_get_revent(fdevents *ev, size_t ndx) {
180 if (ev->event_get_revent == NULL) SEGFAULT();
182 return ev->event_get_revent(ev, ndx);
185 int fdevent_event_get_fd(fdevents *ev, size_t ndx) {
186 if (ev->event_get_fd == NULL) SEGFAULT();
188 return ev->event_get_fd(ev, ndx);
191 fdevent_handler fdevent_get_handler(fdevents *ev, int fd) {
192 if (ev->fdarray[fd] == NULL) SEGFAULT();
193 if (ev->fdarray[fd]->fd != fd) SEGFAULT();
195 return ev->fdarray[fd]->handler;
198 void * fdevent_get_context(fdevents *ev, int fd) {
199 if (ev->fdarray[fd] == NULL) SEGFAULT();
200 if (ev->fdarray[fd]->fd != fd) SEGFAULT();
202 return ev->fdarray[fd]->ctx;
205 void fd_close_on_exec(int fd) {
206 #ifdef FD_CLOEXEC
207 if (fd < 0) return;
208 force_assert(-1 != fcntl(fd, F_SETFD, FD_CLOEXEC));
209 #else
210 UNUSED(fd);
211 #endif
214 int fdevent_fcntl_set(fdevents *ev, int fd) {
215 fd_close_on_exec(fd);
216 if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd);
217 #ifdef O_NONBLOCK
218 return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
219 #else
220 return 0;
221 #endif
225 int fdevent_event_next_fdndx(fdevents *ev, int ndx) {
226 if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx);
228 return -1;