2 event_select.c -- select(2) support
3 Copyright (C) 2012-2022 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.
25 static bool running = false;
26 static fd_set readfds;
27 static fd_set writefds;
29 void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags) {
41 if(!splay_insert_node(&io_tree, &io->node)) {
46 void io_set(io_t *io, int flags) {
47 if(flags == io->flags) {
58 FD_SET(io->fd, &readfds);
60 FD_CLR(io->fd, &readfds);
63 if(flags & IO_WRITE) {
64 FD_SET(io->fd, &writefds);
66 FD_CLR(io->fd, &writefds);
70 void io_del(io_t *io) {
73 splay_unlink_node(&io_tree, &io->node);
78 bool event_loop(void) {
86 struct timeval *tv = timeout_execute(&diff);
88 memcpy(&readable, &readfds, sizeof(readable));
89 memcpy(&writable, &writefds, sizeof(writable));
94 io_t *last = io_tree.tail->data;
95 maxfds = last->fd + 1;
98 int n = select(maxfds, &readable, &writable, NULL, tv);
101 if(sockwouldblock(sockerrno)) {
112 unsigned int curgen = io_tree.generation;
114 for splay_each(io_t, io, &io_tree) {
115 if(FD_ISSET(io->fd, &writable)) {
116 io->cb(io->data, IO_WRITE);
117 } else if(FD_ISSET(io->fd, &readable)) {
118 io->cb(io->data, IO_READ);
124 There are scenarios in which the callback will remove another io_t from the tree
125 (e.g. closing a double connection). Since splay_each does not support that, we
126 need to exit the loop if that happens. That's okay, since any remaining events will
127 get picked up by the next select() call.
129 if(curgen != io_tree.generation) {
138 void event_exit(void) {