2 event.c -- I/O, timeout and signal event handling
3 Copyright (C) 2012-2021 Guus Sliepen <guus@tinc-vpn.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 static fd_set readfds;
28 static fd_set writefds;
30 static const long READ_EVENTS = FD_READ | FD_ACCEPT | FD_CLOSE;
31 static const long WRITE_EVENTS = FD_WRITE | FD_CONNECT;
32 static DWORD event_count = 0;
36 static int io_compare(const io_t *a, const io_t *b) {
41 if(a->event < b->event) {
45 if(a->event > b->event) {
53 static int timeout_compare(const timeout_t *a, const timeout_t *b) {
55 timersub(&a->tv, &b->tv, &diff);
65 if(diff.tv_usec < 0) {
69 if(diff.tv_usec > 0) {
84 static splay_tree_t io_tree = {.compare = (splay_compare_t)io_compare};
85 static splay_tree_t timeout_tree = {.compare = (splay_compare_t)timeout_compare};
87 void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags) {
96 io->event = WSACreateEvent();
98 if(io->event == WSA_INVALID_EVENT) {
111 if(!splay_insert_node(&io_tree, &io->node)) {
117 void io_add_event(io_t *io, io_cb_t cb, void *data, WSAEVENT event) {
119 io_add(io, cb, data, -1, 0);
123 void io_set(io_t *io, int flags) {
124 if(flags == io->flags) {
136 if(flags & IO_READ) {
137 FD_SET(io->fd, &readfds);
139 FD_CLR(io->fd, &readfds);
142 if(flags & IO_WRITE) {
143 FD_SET(io->fd, &writefds);
145 FD_CLR(io->fd, &writefds);
151 if(flags & IO_WRITE) {
152 events |= WRITE_EVENTS;
155 if(flags & IO_READ) {
156 events |= READ_EVENTS;
159 if(WSAEventSelect(io->fd, io->event, events) != 0) {
166 void io_del(io_t *io) {
174 if(io->fd != -1 && WSACloseEvent(io->event) == FALSE) {
181 splay_unlink_node(&io_tree, &io->node);
185 void timeout_add(timeout_t *timeout, timeout_cb_t cb, void *data, struct timeval *tv) {
187 timeout->data = data;
188 timeout->node.data = timeout;
190 timeout_set(timeout, tv);
193 void timeout_set(timeout_t *timeout, struct timeval *tv) {
194 if(timerisset(&timeout->tv)) {
195 splay_unlink_node(&timeout_tree, &timeout->node);
199 gettimeofday(&now, NULL);
202 timeradd(&now, tv, &timeout->tv);
204 if(!splay_insert_node(&timeout_tree, &timeout->node)) {
209 void timeout_del(timeout_t *timeout) {
214 splay_unlink_node(&timeout_tree, &timeout->node);
216 timeout->tv = (struct timeval) {
225 # define NSIG (_SIGMAX + 1) /* For QNX */
229 static io_t signalio;
230 static int pipefd[2] = {-1, -1};
231 static signal_t *signal_handle[NSIG + 1] = {};
233 static void signal_handler(int signum) {
234 unsigned char num = signum;
235 write(pipefd[1], &num, 1);
238 static void signalio_handler(void *data, int flags) {
241 unsigned char signum;
243 if(read(pipefd[0], &signum, 1) != 1) {
247 signal_t *sig = signal_handle[signum];
254 static void pipe_init(void) {
256 io_add(&signalio, signalio_handler, NULL, pipefd[0], IO_READ);
260 void signal_add(signal_t *sig, signal_cb_t cb, void *data, int signum) {
265 sig->signum = signum;
269 if(pipefd[0] == -1) {
273 signal(signum, signal_handler);
275 signal_handle[signum] = sig;
278 void signal_del(signal_t *sig) {
283 signal(sig->signum, SIG_DFL);
285 signal_handle[sig->signum] = NULL;
290 static struct timeval *get_time_remaining(struct timeval *diff) {
291 gettimeofday(&now, NULL);
292 struct timeval *tv = NULL;
294 while(timeout_tree.head) {
295 timeout_t *timeout = timeout_tree.head->data;
296 timersub(&timeout->tv, &now, diff);
298 if(diff->tv_sec < 0) {
299 timeout->cb(timeout->data);
301 if(timercmp(&timeout->tv, &now, <)) {
302 timeout_del(timeout);
313 bool event_loop(void) {
322 struct timeval *tv = get_time_remaining(&diff);
323 memcpy(&readable, &readfds, sizeof(readable));
324 memcpy(&writable, &writefds, sizeof(writable));
329 io_t *last = io_tree.tail->data;
333 int n = select(fds, &readable, &writable, NULL, tv);
336 if(sockwouldblock(sockerrno)) {
347 unsigned int curgen = io_tree.generation;
349 for splay_each(io_t, io, &io_tree) {
350 if(FD_ISSET(io->fd, &writable)) {
351 io->cb(io->data, IO_WRITE);
352 } else if(FD_ISSET(io->fd, &readable)) {
353 io->cb(io->data, IO_READ);
359 There are scenarios in which the callback will remove another io_t from the tree
360 (e.g. closing a double connection). Since splay_each does not support that, we
361 need to exit the loop if that happens. That's okay, since any remaining events will
362 get picked up by the next select() call.
364 if(curgen != io_tree.generation) {
374 struct timeval *tv = get_time_remaining(&diff);
375 DWORD timeout_ms = tv ? (DWORD)(tv->tv_sec * 1000 + tv->tv_usec / 1000 + 1) : WSA_INFINITE;
383 For some reason, Microsoft decided to make the FD_WRITE event edge-triggered instead of level-triggered,
384 which is the opposite of what select() does. In practice, that means that if a FD_WRITE event triggers,
385 it will never trigger again until a send() returns EWOULDBLOCK. Since the semantics of this event loop
386 is that write events are level-triggered (i.e. they continue firing until the socket is full), we need
387 to emulate these semantics by making sure we fire each IO_WRITE that is still writeable.
389 Note that technically FD_CLOSE has the same problem, but it's okay because user code does not rely on
390 this event being fired again if ignored.
392 unsigned int curgen = io_tree.generation;
394 for splay_each(io_t, io, &io_tree) {
395 if(io->flags & IO_WRITE && send(io->fd, NULL, 0, 0) == 0) {
396 io->cb(io->data, IO_WRITE);
398 if(curgen != io_tree.generation) {
404 if(event_count > WSA_MAXIMUM_WAIT_EVENTS) {
405 WSASetLastError(WSA_INVALID_PARAMETER);
409 WSAEVENT events[WSA_MAXIMUM_WAIT_EVENTS];
410 io_t *io_map[WSA_MAXIMUM_WAIT_EVENTS];
411 DWORD event_index = 0;
413 for splay_each(io_t, io, &io_tree) {
414 events[event_index] = io->event;
415 io_map[event_index] = io;
420 * If the generation number changes due to event addition
421 * or removal by a callback we restart the loop.
423 curgen = io_tree.generation;
425 for(DWORD event_offset = 0; event_offset < event_count;) {
426 DWORD result = WSAWaitForMultipleEvents(event_count - event_offset, &events[event_offset], FALSE, timeout_ms, FALSE);
428 if(result == WSA_WAIT_TIMEOUT) {
432 if(result < WSA_WAIT_EVENT_0 || result >= WSA_WAIT_EVENT_0 + event_count - event_offset) {
436 /* Look up io in the map by index. */
437 event_index = result - WSA_WAIT_EVENT_0 + event_offset;
438 io_t *io = io_map[event_index];
443 if(curgen != io_tree.generation) {
447 WSANETWORKEVENTS network_events;
449 if(WSAEnumNetworkEvents(io->fd, io->event, &network_events) != 0) {
453 if(network_events.lNetworkEvents & READ_EVENTS) {
454 io->cb(io->data, IO_READ);
456 if(curgen != io_tree.generation) {
462 The fd might be available for write too. However, if we already fired the read callback, that
463 callback might have deleted the io (e.g. through terminate_connection()), so we can't fire the
464 write callback here. Instead, we loop back and let the writable io loop above handle it.
468 /* Continue checking the rest of the events. */
469 event_offset = event_index + 1;
471 /* Just poll the next time through. */
481 void event_exit(void) {