diff options
Diffstat (limited to 'libnetio')
-rw-r--r-- | libnetio/CMakeLists.txt | 13 | ||||
-rw-r--r-- | libnetio/include/libnetio/netio.h | 27 | ||||
-rw-r--r-- | libnetio/netio_posix.c | 238 |
3 files changed, 0 insertions, 278 deletions
diff --git a/libnetio/CMakeLists.txt b/libnetio/CMakeLists.txt deleted file mode 100644 index fcfecfd..0000000 --- a/libnetio/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# libnetio/CMakeLists.txt - Build script for libnetio support library -# -# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> -# SPDX-Licence-Identifier: AGPL-3.0-or-later - -add_library(libnetio INTERFACE) -target_sources(libnetio INTERFACE - netio_posix.c -) -target_link_libraries(libnetio INTERFACE - libcr_ipc -) -target_include_directories(libnetio SYSTEM INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include) diff --git a/libnetio/include/libnetio/netio.h b/libnetio/include/libnetio/netio.h deleted file mode 100644 index 370d2ca..0000000 --- a/libnetio/include/libnetio/netio.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _NETIO_H_ -#define _NETIO_H_ - -#include <stdbool.h> /* for bool */ -#include <stdint.h> /* for uint16_t */ -#include <stddef.h> /* for size_t */ -#include <sys/types.h> /* for ssize_t */ - -/** Return socket-fd on success, -errno on error. */ -int netio_listen(uint16_t port); -/** Return connection-fd on success, -errno on error. */ -int netio_accept(int sock); -/** Return bytes-read on success, 0 on EOF, -errno on error; a short read is *not* an error. */ -ssize_t netio_read(int conn, void *buf, size_t count); -/** - * Return `count` on success, -errno on error; a short write *is* an - * error. - * - * Writes are *not* guaranteed to be atomic (as this would be - * expensive to implement), so if you have concurrent writers then you - * should arrange for a mutex to protect the connection. - */ -ssize_t netio_write(int conn, void *buf, size_t count); -/** Return 0 on success, -errno on error. */ -int netio_close(int conn, bool rd, bool wr); - -#endif /* _NETIO_H_ */ diff --git a/libnetio/netio_posix.c b/libnetio/netio_posix.c deleted file mode 100644 index f3e9fe0..0000000 --- a/libnetio/netio_posix.c +++ /dev/null @@ -1,238 +0,0 @@ -/* netio_posix.c - netio implementation for POSIX-ish systems - * (actually uses a few GNU extensions) - * - * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> - * SPDX-Licence-Identifier: AGPL-3.0-or-later - */ - -#define _GNU_SOURCE /* for pthread_sigqueue(3gnu) */ -/* misc */ -#include <assert.h> /* for assert() */ -#include <errno.h> /* for errno, EAGAIN, EINVAL */ -#include <error.h> /* for error(3gnu) */ -#include <stdlib.h> /* for abs(), shutdown(), SHUT_RD, SHUT_WR, SHUT_RDWR */ -#include <unistd.h> /* for read(), write() */ -/* net */ -#include <arpa/inet.h> /* for htons(3p) */ -#include <netinet/in.h> /* for struct sockaddr_in */ -#include <sys/socket.h> /* for struct sockaddr, socket(), SOCK_* flags, setsockopt(), SOL_SOCKET, SO_REUSEADDR, bind(), listen(), accept() */ -/* async */ -#include <pthread.h> /* for pthread_* */ -#include <signal.h> /* for siginfo_t, struct sigaction, enum sigval, sigaction(), SIGRTMIN, SIGRTMAX, SA_SIGINFO */ - -#include <libcr/coroutine.h> - -#include <libnetio/netio.h> - -/* configuration **************************************************************/ - -#include "config.h" - -#ifndef CONFIG_NETIO_NUM_CONNS -# error config.h must define CONFIG_NETIO_NUM_CONNS -#endif - -/* common *********************************************************************/ - -#define UNUSED(name) /* name __attribute__ ((unused)) */ - -static int sig_io = 0; - -static void handle_sig_io(int UNUSED(sig), siginfo_t *info, void *UNUSED(ucontext)) { - cr_unpause_from_intrhandler((cid_t)info->si_value.sival_int); -} - -static void _netio_init(void) { - struct sigaction action = {0}; - - if (sig_io) - return; - - sig_io = SIGRTMIN; - if (sig_io > SIGRTMAX) - error(1, 0, "SIGRTMAX exceeded"); - - action.sa_flags = SA_SIGINFO; - action.sa_sigaction = handle_sig_io; - if (sigaction(sig_io, &action, NULL) < 0) - error(1, errno, "sigaction"); -} - -#define WAKE_COROUTINE(args) do { \ - int r; \ - union sigval val = {0}; \ - val.sival_int = (int)((args)->cr_coroutine); \ - do { \ - r = pthread_sigqueue((args)->cr_thread, sig_io, val); \ - assert(r == 0 || r == EAGAIN); \ - } while (r == EAGAIN); \ - } while (0) - -#define RUN_PTHREAD(fn, args) do { \ - pthread_t thread; \ - int r; \ - r = pthread_create(&thread, NULL, fn, args); \ - if (r) \ - return -abs(r); \ - cr_pause_and_yield(); \ - r = pthread_join(thread, NULL); \ - if (r) \ - return -abs(r); \ - } while (0) - -/* listen() *******************************************************************/ - -int netio_listen(uint16_t port) { - int sockfd; - union { - struct sockaddr_in in; - struct sockaddr gen; - } addr = { 0 }; - - _netio_init(); - - addr.in.sin_family = AF_INET; - addr.in.sin_port = htons(port); - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd < 0) - error(1, errno, "socket"); - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0) - error(1, errno, "setsockopt"); - if (bind(sockfd, &addr.gen, sizeof addr) < 0) - error(1, errno, "bind"); - if (listen(sockfd, CONFIG_NETIO_NUM_CONNS) < 0) - error(1, errno, "listen"); - - return sockfd; -} - -/* accept() *******************************************************************/ - -struct _pthread_accept_args { - pthread_t cr_thread; - cid_t cr_coroutine; - - int sockfd; - - int *ret; -}; - -void *_pthread_accept(void *_args) { - struct _pthread_accept_args *args = _args; - *(args->ret) = accept(args->sockfd, NULL, NULL); - if (*(args->ret) < 0) - *(args->ret) = -errno; - WAKE_COROUTINE(args); - return NULL; -}; - -int netio_accept(int sock) { - int ret; - struct _pthread_accept_args args = { - .cr_thread = pthread_self(), - .cr_coroutine = cr_getcid(), - .sockfd = sock, - .ret = &ret, - }; - RUN_PTHREAD(_pthread_accept, &args); - return ret; -} - -/* read() *********************************************************************/ - -struct _pthread_read_args { - pthread_t cr_thread; - cid_t cr_coroutine; - - int connfd; - void *buf; - size_t count; - - ssize_t *ret; -}; - -void *_pthread_read(void *_args) { - struct _pthread_read_args *args = _args; - *(args->ret) = read(args->connfd, args->buf, args->count); - if (*(args->ret) < 0) - *(args->ret) = -errno; - WAKE_COROUTINE(args); - return NULL; -}; - -ssize_t netio_read(int conn, void *buf, size_t count) { - ssize_t ret; - struct _pthread_read_args args = { - .cr_thread = pthread_self(), - .cr_coroutine = cr_getcid(), - - .connfd = conn, - .buf = buf, - .count = count, - - .ret = &ret, - }; - RUN_PTHREAD(_pthread_read, &args); - return ret; -} - -/* write() ********************************************************************/ - -struct _pthread_write_args { - pthread_t cr_thread; - cid_t cr_coroutine; - - int connfd; - void *buf; - size_t count; - - ssize_t *ret; -}; - -void *_pthread_write(void *_args) { - struct _pthread_read_args *args = _args; - size_t done = 0; - while (done < args->count) { - ssize_t r = write(args->connfd, args->buf, args->count); - if (r < 0) { - *(args->ret) = -errno; - break; - } - done += r; - } - if (done == args->count) - *(args->ret) = done; - WAKE_COROUTINE(args); - return NULL; -}; - -ssize_t netio_write(int conn, void *buf, size_t count) { - ssize_t ret; - struct _pthread_write_args args = { - .cr_thread = pthread_self(), - .cr_coroutine = cr_getcid(), - - .connfd = conn, - .buf = buf, - .count = count, - - .ret = &ret, - }; - RUN_PTHREAD(_pthread_write, &args); - return ret; -} - -/* close() ********************************************************************/ - -int netio_close(int conn, bool rd, bool wr) { - int how; - if (rd && wr) - how = SHUT_RDWR; - else if (rd && !wr) - how = SHUT_RD; - else if (!rd && wr) - how = SHUT_WR; - else - return -EINVAL; - return shutdown(conn, how) ? -errno : 0; -} |