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 
fdevent_poll_free(fdevents * ev)23 static void fdevent_poll_free(fdevents *ev) {
24 	free(ev->pollfds);
25 	if (ev->unused.ptr) free(ev->unused.ptr);
26 }
27 
fdevent_poll_event_del(fdevents * ev,int fde_ndx,int fd)28 static 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
64 static 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 
fdevent_poll_event_set(fdevents * ev,int fde_ndx,int fd,int events)76 static 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 
fdevent_poll_poll(fdevents * ev,int timeout_ms)117 static 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 
fdevent_poll_event_get_revent(fdevents * ev,size_t ndx)124 static 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 
fdevent_poll_event_get_fd(fdevents * ev,size_t ndx)156 static int fdevent_poll_event_get_fd(fdevents *ev, size_t ndx) {
157 	return ev->pollfds[ndx].fd;
158 }
159 
fdevent_poll_event_next_fdndx(fdevents * ev,int ndx)160 static 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 
fdevent_poll_init(fdevents * ev)171 int 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
fdevent_poll_init(fdevents * ev)193 int 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