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