summaryrefslogtreecommitdiffstats
path: root/src/poll.c
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2015-03-22 00:57:16 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2015-03-22 00:57:16 +0100
commitdf387f268f8d30d0a21731406bf6031cd6ba9588 (patch)
tree1f1465524c01826a61f7c5f7631c43cce41e6b62 /src/poll.c
parent5266f01d3295e7ac79cf25674167382b86817019 (diff)
downloadfastd-df387f268f8d30d0a21731406bf6031cd6ba9588.tar
fastd-df387f268f8d30d0a21731406bf6031cd6ba9588.zip
Refactor poll API
Diffstat (limited to 'src/poll.c')
-rw-r--r--src/poll.c260
1 files changed, 93 insertions, 167 deletions
diff --git a/src/poll.c b/src/poll.c
index 499a339..6c83f97 100644
--- a/src/poll.c
+++ b/src/poll.c
@@ -66,6 +66,47 @@ static inline int handshake_timeout(void) {
}
+/** Handles a file descriptor that was selected on */
+static inline void handle_fd(fastd_poll_fd_t *fd, bool input, bool error) {
+ switch (fd->type) {
+ case POLL_TYPE_ASYNC:
+ if (input)
+ fastd_async_handle();
+ break;
+
+#ifdef WITH_STATUS_SOCKET
+ case POLL_TYPE_STATUS:
+ if (input)
+ fastd_status_handle();
+ break;
+#endif
+
+ case POLL_TYPE_IFACE:
+ if (input)
+ fastd_tuntap_handle();
+ break;
+
+ case POLL_TYPE_SOCKET:
+ {
+ fastd_socket_t *sock = container_of(fd, fastd_socket_t, fd);
+ if (error) {
+ if (sock->peer)
+ fastd_peer_reset_socket(sock->peer);
+ else
+ fastd_socket_error(sock);
+ }
+ else if (input) {
+ fastd_receive(sock);
+ }
+ }
+ break;
+
+ default:
+ exit_bug("unknown FD type");
+ }
+}
+
+
#ifdef USE_EPOLL
@@ -84,25 +125,6 @@ void fastd_poll_init(void) {
ctx.epoll_fd = epoll_create(1);
if (ctx.epoll_fd < 0)
exit_errno("epoll_create1");
-
- struct epoll_event event_async = {
- .events = EPOLLIN,
- .data.ptr = &ctx.async_rfd,
- };
- if (epoll_ctl(ctx.epoll_fd, EPOLL_CTL_ADD, ctx.async_rfd, &event_async) < 0)
- exit_errno("epoll_ctl");
-
-#ifdef WITH_STATUS_SOCKET
- if (ctx.status_fd >= 0) {
- struct epoll_event event_status = {
- .events = EPOLLIN,
- .data.ptr = &ctx.status_fd,
- };
-
- if (epoll_ctl(ctx.epoll_fd, EPOLL_CTL_ADD, ctx.status_fd, &event_status) < 0)
- exit_errno("epoll_ctl");
- }
-#endif
}
void fastd_poll_free(void) {
@@ -110,42 +132,25 @@ void fastd_poll_free(void) {
pr_warn_errno("closing EPOLL: close");
}
-void fastd_poll_set_fd_tuntap(void) {
- struct epoll_event event = {
- .events = EPOLLIN,
- .data.ptr = &ctx.tunfd,
- };
- if (epoll_ctl(ctx.epoll_fd, EPOLL_CTL_ADD, ctx.tunfd, &event) < 0)
- exit_errno("epoll_ctl");
-}
-
-void fastd_poll_set_fd_sock(size_t i) {
- struct epoll_event event = {
- .events = EPOLLIN,
- .data.ptr = &ctx.socks[i],
- };
- if (epoll_ctl(ctx.epoll_fd, EPOLL_CTL_ADD, ctx.socks[i].fd, &event) < 0)
- exit_errno("epoll_ctl");
-}
-
-void fastd_poll_set_fd_peer(size_t i) {
- fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i);
- if (!peer->sock || !fastd_peer_is_socket_dynamic(peer))
- return;
+void fastd_poll_fd_register(fastd_poll_fd_t *fd) {
+ if (fd->fd < 0)
+ exit_bug("fastd_poll_fd_register: invalid FD");
struct epoll_event event = {
.events = EPOLLIN,
- .data.ptr = peer->sock,
+ .data.ptr = fd,
};
- if (epoll_ctl(ctx.epoll_fd, EPOLL_CTL_ADD, peer->sock->fd, &event) < 0)
+
+ if (epoll_ctl(ctx.epoll_fd, EPOLL_CTL_ADD, fd->fd, &event) < 0)
exit_errno("epoll_ctl");
}
-void fastd_poll_add_peer(void) {
-}
+bool fastd_poll_fd_close(fastd_poll_fd_t *fd) {
+ if (epoll_ctl(ctx.epoll_fd, EPOLL_CTL_DEL, fd->fd, NULL) < 0)
+ exit_errno("epoll_ctl");
-void fastd_poll_delete_peer(UNUSED size_t i) {
+ return (close(fd->fd) == 0);
}
@@ -170,115 +175,44 @@ void fastd_poll_handle(void) {
return;
size_t i;
- for (i = 0; i < (size_t)ret; i++) {
- if (events[i].data.ptr == &ctx.tunfd) {
- if (events[i].events & EPOLLIN)
- fastd_tuntap_handle();
- }
- else if (events[i].data.ptr == &ctx.async_rfd) {
- if (events[i].events & EPOLLIN)
- fastd_async_handle();
- }
-#ifdef WITH_STATUS_SOCKET
- else if (events[i].data.ptr == &ctx.status_fd) {
- if (events[i].events & EPOLLIN)
- fastd_status_handle();
- }
-#endif
- else {
- fastd_socket_t *sock = events[i].data.ptr;
-
- if (events[i].events & (EPOLLERR|EPOLLHUP)) {
- if (sock->peer)
- fastd_peer_reset_socket(sock->peer);
- else
- fastd_socket_error(sock);
- }
- else if (events[i].events & EPOLLIN) {
- fastd_receive(sock);
- }
- }
- }
+ for (i = 0; i < (size_t)ret; i++)
+ handle_fd(events[i].data.ptr,
+ events[i].events & EPOLLIN,
+ events[i].events & (EPOLLERR|EPOLLHUP));
}
#else
void fastd_poll_init(void) {
- VECTOR_RESIZE(ctx.pollfds, 3 + ctx.n_socks + VECTOR_LEN(ctx.peers));
-
- VECTOR_INDEX(ctx.pollfds, 0) = (struct pollfd) {
- .fd = -1,
- .events = POLLIN,
- .revents = 0,
- };
-
- VECTOR_INDEX(ctx.pollfds, 1) = (struct pollfd) {
- .fd = ctx.async_rfd,
- .events = POLLIN,
- .revents = 0,
- };
-
- VECTOR_INDEX(ctx.pollfds, 2) = (struct pollfd) {
-#ifdef WITH_STATUS_SOCKET
- .fd = ctx.status_fd,
-#else
- .fd = -1,
-#endif
- .events = POLLIN,
- .revents = 0,
- };
-
- size_t i;
- for (i = 0; i < ctx.n_socks + VECTOR_LEN(ctx.peers); i++) {
- VECTOR_INDEX(ctx.pollfds, 3+i) = (struct pollfd) {
- .fd = -1,
- .events = POLLIN,
- .revents = 0,
- };
- }
}
void fastd_poll_free(void) {
+ VECTOR_FREE(ctx.fds);
VECTOR_FREE(ctx.pollfds);
}
-void fastd_poll_set_fd_tuntap(void) {
- VECTOR_INDEX(ctx.pollfds, 0).fd = ctx.tunfd;
-}
-
-void fastd_poll_set_fd_sock(size_t i) {
- VECTOR_INDEX(ctx.pollfds, 3+i).fd = ctx.socks[i].fd;
-}
+void fastd_poll_fd_register(fastd_poll_fd_t *fd) {
+ if (fd->fd < 0)
+ exit_bug("fastd_poll_fd_register: invalid FD");
-void fastd_poll_set_fd_peer(size_t i) {
- if (!VECTOR_LEN(ctx.pollfds))
- exit_bug("fastd_poll_set_fd_peer: polling not initialized yet");
+ while (VECTOR_LEN(ctx.fds) <= (size_t)fd->fd)
+ VECTOR_ADD(ctx.fds, NULL);
- fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i);
+ VECTOR_INDEX(ctx.fds, fd->fd) = fd;
- if (!peer->sock || !fastd_peer_is_socket_dynamic(peer))
- VECTOR_INDEX(ctx.pollfds, 3+ctx.n_socks+i).fd = -1;
- else
- VECTOR_INDEX(ctx.pollfds, 3+ctx.n_socks+i).fd = peer->sock->fd;
+ VECTOR_RESIZE(ctx.pollfds, 0);
}
-void fastd_poll_add_peer(void) {
- if (!VECTOR_LEN(ctx.pollfds))
- /* Polling is not initialized yet */
- return;
+bool fastd_poll_fd_close(fastd_poll_fd_t *fd) {
+ if (fd->fd < 0 || (size_t)fd->fd >= VECTOR_LEN(ctx.fds))
+ exit_bug("fastd_poll_fd_close: invalid FD");
- struct pollfd pollfd = {
- .fd = -1,
- .events = POLLIN,
- .revents = 0,
- };
+ VECTOR_INDEX(ctx.fds, fd->fd) = NULL;
- VECTOR_ADD(ctx.pollfds, pollfd);
-}
+ VECTOR_RESIZE(ctx.pollfds, 0);
-void fastd_poll_delete_peer(size_t i) {
- VECTOR_DELETE(ctx.pollfds, 3+ctx.n_socks+i);
+ return (close(fd->fd) == 0);
}
@@ -294,8 +228,20 @@ void fastd_poll_handle(void) {
if (timeout < 0 || timeout > maintenance_timeout)
timeout = maintenance_timeout;
- if (VECTOR_LEN(ctx.pollfds) != 3 + ctx.n_socks + VECTOR_LEN(ctx.peers))
- exit_bug("fd count mismatch");
+ if (!VECTOR_LEN(ctx.pollfds)) {
+ for (i = 0; i < VECTOR_LEN(ctx.fds); i++) {
+ fastd_poll_fd_t *fd = VECTOR_INDEX(ctx.fds, i);
+ if (!fd)
+ continue;
+
+ struct pollfd pollfd = {
+ .fd = fd->fd,
+ .events = POLLIN,
+ .revents = 0,
+ };
+ VECTOR_ADD(ctx.pollfds, pollfd);
+ }
+ }
sigset_t set, oldset;
sigemptyset(&set);
@@ -334,6 +280,8 @@ void fastd_poll_handle(void) {
}
if (ret > 0) {
+ ret = 0;
+
for (i = 0; i < VECTOR_LEN(ctx.pollfds); i++) {
struct pollfd *pollfd = &VECTOR_INDEX(ctx.pollfds, i);
pollfd->revents = 0;
@@ -345,6 +293,9 @@ void fastd_poll_handle(void) {
pollfd->revents |= POLLIN;
if (FD_ISSET(pollfd->fd, &errfds))
pollfd->revents |= POLLERR;
+
+ if (pollfd->revents)
+ ret++;
}
}
@@ -360,39 +311,14 @@ void fastd_poll_handle(void) {
if (ret <= 0)
return;
- if (VECTOR_INDEX(ctx.pollfds, 0).revents & POLLIN)
- fastd_tuntap_handle();
- if (VECTOR_INDEX(ctx.pollfds, 1).revents & POLLIN)
- fastd_async_handle();
-
-#ifdef WITH_STATUS_SOCKET
- if (VECTOR_INDEX(ctx.pollfds, 2).revents & POLLIN)
- fastd_status_handle();
-#endif
-
- for (i = 0; i < ctx.n_socks; i++) {
- if (VECTOR_INDEX(ctx.pollfds, 3+i).revents & (POLLERR|POLLHUP|POLLNVAL)) {
- fastd_socket_error(&ctx.socks[i]);
- VECTOR_INDEX(ctx.pollfds, 3+i).fd = -1;
- }
- else if (VECTOR_INDEX(ctx.pollfds, 3+i).revents & POLLIN) {
- fastd_receive(&ctx.socks[i]);
- }
- }
+ for (i = 0; i < VECTOR_LEN(ctx.pollfds) && ret > 0; i++) {
+ struct pollfd *pollfd = &VECTOR_INDEX(ctx.pollfds, i);
- for (i = 0; i < VECTOR_LEN(ctx.peers); i++) {
- fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i);
+ if (pollfd->revents)
+ ret--;
- if (VECTOR_INDEX(ctx.pollfds, 3+ctx.n_socks+i).revents & (POLLERR|POLLHUP|POLLNVAL)) {
- fastd_peer_reset_socket(peer);
- }
- else if (VECTOR_INDEX(ctx.pollfds, 3+ctx.n_socks+i).revents & POLLIN) {
- fastd_receive(peer->sock);
- }
+ handle_fd(VECTOR_INDEX(ctx.fds, pollfd->fd), pollfd->revents & POLLIN, pollfd->revents & (POLLERR|POLLHUP|POLLNVAL));
}
-
- if (VECTOR_LEN(ctx.pollfds) != 3 + ctx.n_socks + VECTOR_LEN(ctx.peers))
- exit_bug("fd count mismatch");
}
#endif