• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/lighttpd-1.4.39/src/
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_LINUX_EPOLL
16
17# include <sys/epoll.h>
18
19static void fdevent_linux_sysepoll_free(fdevents *ev) {
20	close(ev->epoll_fd);
21	free(ev->epoll_events);
22}
23
24static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) {
25	struct epoll_event ep;
26
27	if (fde_ndx < 0) return -1;
28
29	memset(&ep, 0, sizeof(ep));
30
31	ep.data.fd = fd;
32	ep.data.ptr = NULL;
33
34	if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) {
35		log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
36			"epoll_ctl failed: ", strerror(errno), ", dying");
37
38		SEGFAULT();
39
40		return 0;
41	}
42
43
44	return -1;
45}
46
47static int fdevent_linux_sysepoll_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
48	struct epoll_event ep;
49	int add = 0;
50
51	if (fde_ndx == -1) add = 1;
52
53	memset(&ep, 0, sizeof(ep));
54
55	ep.events = 0;
56
57	if (events & FDEVENT_IN)  ep.events |= EPOLLIN;
58	if (events & FDEVENT_OUT) ep.events |= EPOLLOUT;
59
60	/**
61	 *
62	 * with EPOLLET we don't get a FDEVENT_HUP
63	 * if the close is delay after everything has
64	 * sent.
65	 *
66	 */
67
68	ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */;
69
70	ep.data.ptr = NULL;
71	ep.data.fd = fd;
72
73	if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) {
74		log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
75			"epoll_ctl failed: ", strerror(errno), ", dying");
76
77		SEGFAULT();
78
79		return 0;
80	}
81
82	return fd;
83}
84
85static int fdevent_linux_sysepoll_poll(fdevents *ev, int timeout_ms) {
86	return epoll_wait(ev->epoll_fd, ev->epoll_events, ev->maxfds, timeout_ms);
87}
88
89static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) {
90	int events = 0, e;
91
92	e = ev->epoll_events[ndx].events;
93	if (e & EPOLLIN) events |= FDEVENT_IN;
94	if (e & EPOLLOUT) events |= FDEVENT_OUT;
95	if (e & EPOLLERR) events |= FDEVENT_ERR;
96	if (e & EPOLLHUP) events |= FDEVENT_HUP;
97	if (e & EPOLLPRI) events |= FDEVENT_PRI;
98
99	return events;
100}
101
102static int fdevent_linux_sysepoll_event_get_fd(fdevents *ev, size_t ndx) {
103# if 0
104	log_error_write(ev->srv, __FILE__, __LINE__, "SD, D",
105		"fdevent_linux_sysepoll_event_get_fd: ", (int) ndx, ev->epoll_events[ndx].data.fd);
106# endif
107
108	return ev->epoll_events[ndx].data.fd;
109}
110
111static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) {
112	size_t i;
113
114	UNUSED(ev);
115
116	i = (ndx < 0) ? 0 : ndx + 1;
117
118	return i;
119}
120
121int fdevent_linux_sysepoll_init(fdevents *ev) {
122	ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
123#define SET(x) \
124	ev->x = fdevent_linux_sysepoll_##x;
125
126	SET(free);
127	SET(poll);
128
129	SET(event_del);
130	SET(event_set);
131
132	SET(event_next_fdndx);
133	SET(event_get_fd);
134	SET(event_get_revent);
135
136	if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) {
137		log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
138			"epoll_create failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\"");
139
140		return -1;
141	}
142
143	fd_close_on_exec(ev->epoll_fd);
144
145	ev->epoll_events = malloc(ev->maxfds * sizeof(*ev->epoll_events));
146
147	return 0;
148}
149
150#else
151int fdevent_linux_sysepoll_init(fdevents *ev) {
152	UNUSED(ev);
153
154	log_error_write(ev->srv, __FILE__, __LINE__, "S",
155		"linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"");
156
157	return -1;
158}
159#endif
160