diff options
Diffstat (limited to 'libhw_cr/host_net.c')
-rw-r--r-- | libhw_cr/host_net.c | 340 |
1 files changed, 204 insertions, 136 deletions
diff --git a/libhw_cr/host_net.c b/libhw_cr/host_net.c index 6ed6e46..e68ccf8 100644 --- a/libhw_cr/host_net.c +++ b/libhw_cr/host_net.c @@ -7,11 +7,13 @@ #define _GNU_SOURCE /* for pthread_sigqueue(3gnu) */ /* misc */ #include <errno.h> /* for errno, EAGAIN, EINVAL */ +#define error __error #include <error.h> /* for error(3gnu) */ +#undef error #include <stdlib.h> /* for abs(), shutdown(), SHUT_RD, SHUT_WR, SHUT_RDWR */ -#include <unistd.h> /* for read(), write() */ +#include <sys/uio.h> /* for readv(), writev(), struct iovec */ /* net */ -#include <arpa/inet.h> /* for htons(3p) */ +#include <arpa/inet.h> /* for htons() */ #include <netinet/in.h> /* for struct sockaddr_in */ #include <sys/socket.h> /* for struct sockaddr{,_storage}, SOCK_*, SOL_*, SO_*, socket(), setsockopt(), bind(), listen(), accept() */ /* async */ @@ -19,9 +21,10 @@ #include <signal.h> /* for siginfo_t, struct sigaction, enum sigval, sigaction(), SA_SIGINFO */ #include <libcr/coroutine.h> +#include <libmisc/alloc.h> #include <libmisc/assert.h> #include <libmisc/macro.h> -#include <libobj/obj.h> +#include <libmisc/obj.h> #include <libhw/generic/alarmclock.h> @@ -30,18 +33,18 @@ #include "host_util.h" /* for host_sigrt_alloc(), ns_to_host_us_time() */ -LO_IMPLEMENTATION_C(io_closer, struct hostnet_tcp_listener, hostnet_tcplist, static); -LO_IMPLEMENTATION_C(net_stream_listener, struct hostnet_tcp_listener, hostnet_tcplist, static); +LO_IMPLEMENTATION_C(io_closer, struct hostnet_tcp_listener, hostnet_tcplist); +LO_IMPLEMENTATION_C(net_stream_listener, struct hostnet_tcp_listener, hostnet_tcplist); -LO_IMPLEMENTATION_C(io_reader, struct _hostnet_tcp_conn, hostnet_tcp, static); -LO_IMPLEMENTATION_C(io_writer, struct _hostnet_tcp_conn, hostnet_tcp, static); -LO_IMPLEMENTATION_C(io_readwriter, struct _hostnet_tcp_conn, hostnet_tcp, static); -LO_IMPLEMENTATION_C(io_closer, struct _hostnet_tcp_conn, hostnet_tcp, static); -LO_IMPLEMENTATION_C(io_bidi_closer, struct _hostnet_tcp_conn, hostnet_tcp, static); -LO_IMPLEMENTATION_C(net_stream_conn, struct _hostnet_tcp_conn, hostnet_tcp, static); +LO_IMPLEMENTATION_STATIC(io_reader, struct _hostnet_tcp_conn, hostnet_tcp); +LO_IMPLEMENTATION_STATIC(io_writer, struct _hostnet_tcp_conn, hostnet_tcp); +LO_IMPLEMENTATION_STATIC(io_readwriter, struct _hostnet_tcp_conn, hostnet_tcp); +LO_IMPLEMENTATION_STATIC(io_closer, struct _hostnet_tcp_conn, hostnet_tcp); +LO_IMPLEMENTATION_STATIC(io_bidi_closer, struct _hostnet_tcp_conn, hostnet_tcp); +LO_IMPLEMENTATION_STATIC(net_stream_conn, struct _hostnet_tcp_conn, hostnet_tcp); -LO_IMPLEMENTATION_C(io_closer, struct hostnet_udp_conn, hostnet_udp, static); -LO_IMPLEMENTATION_C(net_packet_conn, struct hostnet_udp_conn, hostnet_udp, static); +LO_IMPLEMENTATION_C(io_closer, struct hostnet_udp_conn, hostnet_udp); +LO_IMPLEMENTATION_C(net_packet_conn, struct hostnet_udp_conn, hostnet_udp); /* common *********************************************************************/ @@ -52,7 +55,7 @@ static void hostnet_handle_sig_io(int LM_UNUSED(sig), siginfo_t *info, void *LM_ } static void hostnet_init(void) { - struct sigaction action = {0}; + struct sigaction action = {}; if (hostnet_sig_io) return; @@ -62,12 +65,12 @@ static void hostnet_init(void) { action.sa_flags = SA_SIGINFO; action.sa_sigaction = hostnet_handle_sig_io; if (sigaction(hostnet_sig_io, &action, NULL) < 0) - error(1, errno, "sigaction"); + __error(1, errno, "sigaction"); } #define WAKE_COROUTINE(args) do { \ int r; \ - union sigval val = {0}; \ + union sigval val = {}; \ val.sival_int = (int)((args)->cr_coroutine); \ do { \ r = pthread_sigqueue((args)->cr_thread, \ @@ -77,46 +80,47 @@ static void hostnet_init(void) { } while (r == EAGAIN); \ } while (0) -static inline bool RUN_PTHREAD(void *(*fn)(void *), void *args) { +static inline host_errno_t RUN_PTHREAD(void *(*fn)(void *), void *args) { pthread_t thread; + host_errno_t r; bool saved = cr_save_and_disable_interrupts(); - if (pthread_create(&thread, NULL, fn, args)) - return true; + r = pthread_create(&thread, NULL, fn, args); + if (r) { + cr_restore_interrupts(saved); + return r; + } cr_pause_and_yield(); cr_restore_interrupts(saved); - if (pthread_join(thread, NULL)) - return true; - return false; + return pthread_join(thread, NULL); } enum hostnet_timeout_op { - OP_NONE, + OP_CLOSE, OP_SEND, OP_RECV, }; -static inline ssize_t hostnet_map_negerrno(ssize_t v, enum hostnet_timeout_op op) { - if (v >= 0) - return v; - switch (v) { - case -EHOSTUNREACH: - return -NET_EARP_TIMEOUT; - case -ETIMEDOUT: +static inline error hostnet_error(host_errno_t errnum, enum hostnet_timeout_op op) { + assert(errnum > 0); + switch (errnum) { + case EHOSTUNREACH: + return error_new(E_NET_EARP_TIMEOUT); + case ETIMEDOUT: switch (op) { - case OP_NONE: + case OP_CLOSE: assert_notreached("impossible ETIMEDOUT"); case OP_SEND: - return -NET_EACK_TIMEOUT; + return error_new(E_NET_EACK_TIMEOUT); case OP_RECV: - return -NET_ERECV_TIMEOUT; + return error_new(E_NET_ERECV_TIMEOUT); } assert_notreached("invalid timeout op"); - case -EBADF: - return -NET_ECLOSED; - case -EMSGSIZE: - return -NET_EMSGSIZE; + case EBADF: + return error_new(E_NET_ECLOSED); + case EMSGSIZE: + return error_new(E_POSIX_EMSGSIZE); default: - return -NET_EOTHER; + return errno2lm(errnum); } } @@ -127,7 +131,7 @@ void hostnet_tcp_listener_init(struct hostnet_tcp_listener *self, uint16_t port) union { struct sockaddr_in in; struct sockaddr gen; - } addr = { 0 }; + } addr = {}; hostnet_init(); @@ -135,15 +139,15 @@ void hostnet_tcp_listener_init(struct hostnet_tcp_listener *self, uint16_t port) addr.in.sin_port = htons(port); listenerfd = socket(AF_INET, SOCK_STREAM, 0); if (listenerfd < 0) - error(1, errno, "socket"); + __error(1, errno, "socket"); if (setsockopt(listenerfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0) - error(1, errno, "setsockopt(fd=%d, SO_REUSEADDR=1)", listenerfd); + __error(1, errno, "setsockopt(fd=%d, SO_REUSEADDR=1)", listenerfd); if (setsockopt(listenerfd, SOL_SOCKET, SO_REUSEPORT, &(int){1}, sizeof(int)) < 0) - error(1, errno, "setsockopt(fd=%d, SO_REUSEPORT=1)", listenerfd); + __error(1, errno, "setsockopt(fd=%d, SO_REUSEPORT=1)", listenerfd); if (bind(listenerfd, &addr.gen, sizeof addr) < 0) - error(1, errno, "bind(fd=%d)", listenerfd); + __error(1, errno, "bind(fd=%d)", listenerfd); if (listen(listenerfd, 0) < 0) - error(1, errno, "listen(fd=%d)", listenerfd); + __error(1, errno, "listen(fd=%d)", listenerfd); self->fd = listenerfd; } @@ -157,44 +161,48 @@ struct hostnet_pthread_accept_args { int listenerfd; int *ret_connfd; + host_errno_t *ret_errno; }; static void *hostnet_pthread_accept(void *_args) { struct hostnet_pthread_accept_args *args = _args; *(args->ret_connfd) = accept(args->listenerfd, NULL, NULL); - if (*(args->ret_connfd) < 0) - *(args->ret_connfd) = -errno; + *(args->ret_errno) = errno; WAKE_COROUTINE(args); return NULL; } -static lo_interface net_stream_conn hostnet_tcplist_accept(struct hostnet_tcp_listener *listener) { +net_stream_conn_or_error hostnet_tcplist_accept(struct hostnet_tcp_listener *listener) { assert(listener); int ret_connfd; + host_errno_t ret_errno; struct hostnet_pthread_accept_args args = { .cr_thread = pthread_self(), .cr_coroutine = cr_getcid(), .listenerfd = listener->fd, .ret_connfd = &ret_connfd, + .ret_errno = &ret_errno, }; - if (RUN_PTHREAD(hostnet_pthread_accept, &args)) - return LO_NULL(net_stream_conn); - + host_errno_t thread_errno = RUN_PTHREAD(hostnet_pthread_accept, &args); + if (thread_errno) + return ERROR_NEW_ERR(net_stream_conn, errno2lm(thread_errno)); if (ret_connfd < 0) - return LO_NULL(net_stream_conn); + return ERROR_NEW_ERR(net_stream_conn, hostnet_error(ret_errno, OP_RECV)); listener->active_conn.fd = ret_connfd; listener->active_conn.read_deadline_ns = 0; - return lo_box_hostnet_tcp_as_net_stream_conn(&listener->active_conn); + return ERROR_NEW_VAL(net_stream_conn, LO_BOX(net_stream_conn, &listener->active_conn)); } /* TCP listener close() *******************************************************/ -static int hostnet_tcplist_close(struct hostnet_tcp_listener *listener) { +error hostnet_tcplist_close(struct hostnet_tcp_listener *listener) { assert(listener); - return hostnet_map_negerrno(shutdown(listener->fd, SHUT_RDWR) ? -errno : 0, OP_NONE); + if (shutdown(listener->fd, SHUT_RDWR)) + return hostnet_error(errno, OP_CLOSE); + return ERROR_NULL; } /* TCP read() *****************************************************************/ @@ -214,56 +222,74 @@ struct hostnet_pthread_readv_args { const struct iovec *iov; int iovcnt; - ssize_t *ret; + size_t *ret_size; + host_errno_t *ret_errno; }; static void *hostnet_pthread_readv(void *_args) { struct hostnet_pthread_readv_args *args = _args; - *(args->ret) = setsockopt(args->connfd, SOL_SOCKET, SO_RCVTIMEO, - &args->timeout, sizeof(args->timeout)); - if (*(args->ret) < 0) + int r_i = setsockopt(args->connfd, SOL_SOCKET, SO_RCVTIMEO, + &args->timeout, sizeof(args->timeout)); + if (r_i) { + *args->ret_size = 0; + *args->ret_errno = errno; goto end; + } - *(args->ret) = readv(args->connfd, args->iov, args->iovcnt); - if (*(args->ret) < 0) + ssize_t r_ss = readv(args->connfd, args->iov, args->iovcnt); + if (r_ss < 0) { + *args->ret_size = 0; + *args->ret_errno = errno; goto end; + } + *args->ret_size = r_ss; + *args->ret_errno = 0; end: - if (*(args->ret) < 0) - *(args->ret) = hostnet_map_negerrno(-errno, OP_SEND); WAKE_COROUTINE(args); return NULL; } -static ssize_t hostnet_tcp_readv(struct _hostnet_tcp_conn *conn, const struct iovec *iov, int iovcnt) { +static size_t_or_error hostnet_tcp_readv(struct _hostnet_tcp_conn *conn, const struct rd_iovec *iov, int iovcnt) { assert(conn); assert(iov); assert(iovcnt > 0); + size_t count = 0; + for (int i = 0; i < iovcnt; i++) + count += iov[i].iov_len; + assert(count); - ssize_t ret; + size_t ret_size; + host_errno_t ret_errno; struct hostnet_pthread_readv_args args = { .cr_thread = pthread_self(), .cr_coroutine = cr_getcid(), .connfd = conn->fd, - .iov = iov, + .iov = (const struct iovec *)iov, .iovcnt = iovcnt, - .ret = &ret, + .ret_size = &ret_size, + .ret_errno = &ret_errno, }; if (conn->read_deadline_ns) { uint64_t now_ns = LO_CALL(bootclock, get_time_ns); if (conn->read_deadline_ns < now_ns) - return -NET_ERECV_TIMEOUT; + return ERROR_NEW_ERR(size_t, error_new(E_NET_ERECV_TIMEOUT)); args.timeout = ns_to_host_us_time(conn->read_deadline_ns-now_ns); } else { - args.timeout = (host_us_time_t){0}; + args.timeout = (host_us_time_t){}; } - if (RUN_PTHREAD(hostnet_pthread_readv, &args)) - return -NET_ETHREAD; - return ret; + host_errno_t thread_errno = RUN_PTHREAD(hostnet_pthread_readv, &args); + if (thread_errno) + return ERROR_NEW_ERR(size_t, errno2lm(thread_errno)); + if (ret_errno) + return ERROR_NEW_ERR(size_t, hostnet_error(ret_errno, OP_RECV)); + if (!ret_size) + return ERROR_NEW_ERR(size_t, error_new(E_EOF)); + return ERROR_NEW_VAL(size_t, ret_size); } /* TCP write() ****************************************************************/ @@ -276,14 +302,15 @@ struct hostnet_pthread_writev_args { const struct iovec *iov; int iovcnt; - ssize_t *ret; + size_t *ret_size; + host_errno_t *ret_errno; }; static void *hostnet_pthread_writev(void *_args) { struct hostnet_pthread_writev_args *args = _args; size_t count = 0; - struct iovec *iov = alloca(sizeof(struct iovec)*args->iovcnt); + struct iovec *iov = stack_alloc(args->iovcnt, struct iovec); for (int i = 0; i < args->iovcnt; i++) { iov[i] = args->iov[i]; count += args->iov[i].iov_len; @@ -294,7 +321,7 @@ static void *hostnet_pthread_writev(void *_args) { while (done < count) { ssize_t r = writev(args->connfd, iov, iovcnt); if (r < 0) { - hostnet_map_negerrno(-errno, OP_RECV); + *args->ret_errno = errno; break; } done += r; @@ -309,45 +336,59 @@ static void *hostnet_pthread_writev(void *_args) { } } if (done == count) - *(args->ret) = done; + *args->ret_errno = 0; + *args->ret_size = done; WAKE_COROUTINE(args); return NULL; } -static ssize_t hostnet_tcp_writev(struct _hostnet_tcp_conn *conn, const struct iovec *iov, int iovcnt) { +static size_t_and_error hostnet_tcp_writev(struct _hostnet_tcp_conn *conn, const struct wr_iovec *iov, int iovcnt) { assert(conn); assert(iov); assert(iovcnt > 0); + size_t count = 0; + for (int i = 0; i < iovcnt; i++) + count += iov[i].iov_len; + assert(count); - ssize_t ret; + size_t ret_size; + host_errno_t ret_errno; struct hostnet_pthread_writev_args args = { .cr_thread = pthread_self(), .cr_coroutine = cr_getcid(), .connfd = conn->fd, - .iov = iov, + .iov = (const struct iovec *)iov, .iovcnt = iovcnt, - .ret = &ret, + .ret_size = &ret_size, + .ret_errno = &ret_errno, }; - if (RUN_PTHREAD(hostnet_pthread_writev, &args)) - return -NET_ETHREAD; - return ret; + int thread_errno = RUN_PTHREAD(hostnet_pthread_writev, &args); + if (thread_errno) + return ERROR_AND(size_t, 0, errno2lm(thread_errno)); + return ERROR_AND(size_t, ret_size, ret_errno ? hostnet_error(ret_errno, OP_SEND) : ERROR_NULL); } /* TCP close() ****************************************************************/ -static int hostnet_tcp_close(struct _hostnet_tcp_conn *conn) { +static error hostnet_tcp_close(struct _hostnet_tcp_conn *conn) { assert(conn); - return hostnet_map_negerrno(shutdown(conn->fd, SHUT_RDWR) ? -errno : 0, OP_NONE); + if (shutdown(conn->fd, SHUT_RDWR)) + return hostnet_error(errno, OP_CLOSE); + return ERROR_NULL; } -static int hostnet_tcp_close_read(struct _hostnet_tcp_conn *conn) { +static error hostnet_tcp_close_read(struct _hostnet_tcp_conn *conn) { assert(conn); - return hostnet_map_negerrno(shutdown(conn->fd, SHUT_RD) ? -errno : 0, OP_NONE); + if (shutdown(conn->fd, SHUT_RD)) + return hostnet_error(errno, OP_CLOSE); + return ERROR_NULL; } -static int hostnet_tcp_close_write(struct _hostnet_tcp_conn *conn) { +static error hostnet_tcp_close_write(struct _hostnet_tcp_conn *conn) { assert(conn); - return hostnet_map_negerrno(shutdown(conn->fd, SHUT_WR) ? -errno : 0, OP_NONE); + if (shutdown(conn->fd, SHUT_WR)) + return hostnet_error(errno, OP_CLOSE); + return ERROR_NULL; } /* UDP init() *****************************************************************/ @@ -358,7 +399,7 @@ void hostnet_udp_conn_init(struct hostnet_udp_conn *self, uint16_t port) { struct sockaddr_in in; struct sockaddr gen; struct sockaddr_storage stor; - } addr = { 0 }; + } addr = {}; hostnet_init(); @@ -366,9 +407,11 @@ void hostnet_udp_conn_init(struct hostnet_udp_conn *self, uint16_t port) { addr.in.sin_port = htons(port); fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) - error(1, errno, "socket"); + __error(1, errno, "socket"); + if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &(int){1}, sizeof(int)) < 0) + __error(1, errno, "setsockopt(fd=%d, SO_BROADCAST=1)", fd); if (bind(fd, &addr.gen, sizeof addr) < 0) - error(1, errno, "bind"); + __error(1, errno, "bind"); self->fd = fd; self->read_deadline_ns = 0; @@ -386,7 +429,8 @@ struct hostnet_pthread_sendto_args { struct net_ip4_addr node; uint16_t port; - ssize_t *ret; + size_t *ret_size; + host_errno_t *ret_errno; }; static void *hostnet_pthread_sendto(void *_args) { @@ -395,27 +439,33 @@ static void *hostnet_pthread_sendto(void *_args) { struct sockaddr_in in; struct sockaddr gen; struct sockaddr_storage stor; - } addr = { 0 }; + } addr = {}; addr.in.sin_family = AF_INET; addr.in.sin_addr.s_addr = - (((uint32_t)args->node.octets[0])<<24) | - (((uint32_t)args->node.octets[1])<<16) | - (((uint32_t)args->node.octets[2])<< 8) | - (((uint32_t)args->node.octets[3])<< 0) ; + (((uint32_t)args->node.octets[3])<<24) | + (((uint32_t)args->node.octets[2])<<16) | + (((uint32_t)args->node.octets[1])<< 8) | + (((uint32_t)args->node.octets[0])<< 0) ; addr.in.sin_port = htons(args->port); - *(args->ret) = sendto(args->connfd, args->buf, args->count, 0, &addr.gen, sizeof(addr)); - if (*(args->ret) < 0) - *(args->ret) = hostnet_map_negerrno(-errno, OP_SEND); + ssize_t r = sendto(args->connfd, args->buf, args->count, 0, &addr.gen, sizeof(addr)); + if (r < 0) { + *args->ret_size = 0; + *args->ret_errno = errno; + } else { + *args->ret_size = r; + *args->ret_errno = 0; + } WAKE_COROUTINE(args); return NULL; } -static ssize_t hostnet_udp_sendto(struct hostnet_udp_conn *conn, void *buf, size_t count, - struct net_ip4_addr node, uint16_t port) { +error hostnet_udp_sendto(struct hostnet_udp_conn *conn, void *buf, size_t count, + struct net_ip4_addr node, uint16_t port) { assert(conn); - ssize_t ret; + size_t ret_size; + host_errno_t ret_errno; struct hostnet_pthread_sendto_args args = { .cr_thread = pthread_self(), .cr_coroutine = cr_getcid(), @@ -426,17 +476,21 @@ static ssize_t hostnet_udp_sendto(struct hostnet_udp_conn *conn, void *buf, size .node = node, .port = port, - .ret = &ret, + .ret_size = &ret_size, + .ret_errno = &ret_errno, }; - if (RUN_PTHREAD(hostnet_pthread_sendto, &args)) - return -NET_ETHREAD; - return ret; + int thread_errno = RUN_PTHREAD(hostnet_pthread_sendto, &args); + if (thread_errno) + return errno2lm(thread_errno); + if (ret_errno) + return hostnet_error(ret_errno, OP_SEND); + return ERROR_NULL; } /* UDP recvfrom() *************************************************************/ -static void hostnet_udp_set_recv_deadline(struct hostnet_udp_conn *conn, - uint64_t ts_ns) { +void hostnet_udp_set_recv_deadline(struct hostnet_udp_conn *conn, + uint64_t ts_ns) { assert(conn); conn->read_deadline_ns = ts_ns; @@ -451,7 +505,8 @@ struct hostnet_pthread_recvfrom_args { void *buf; size_t count; - ssize_t *ret_size; + size_t *ret_size; + host_errno_t *ret_errno; struct net_ip4_addr *ret_node; uint16_t *ret_port; }; @@ -463,42 +518,49 @@ static void *hostnet_pthread_recvfrom(void *_args) { struct sockaddr_in in; struct sockaddr gen; struct sockaddr_storage stor; - } addr = { 0 }; - socklen_t addr_size; - - *(args->ret_size) = setsockopt(args->connfd, SOL_SOCKET, SO_RCVTIMEO, - &args->timeout, sizeof(args->timeout)); - if (*(args->ret_size) < 0) + } addr = {}; + socklen_t addr_size = sizeof(addr); + + int r_i = setsockopt(args->connfd, SOL_SOCKET, SO_RCVTIMEO, + &args->timeout, sizeof(args->timeout)); + if (r_i) { + *args->ret_size = 0; + *args->ret_errno = errno; goto end; + } - *(args->ret_size) = recvfrom(args->connfd, args->buf, args->count, - MSG_TRUNC, &addr.gen, &addr_size); - if (*(args->ret_size) < 0) + ssize_t r_ss = recvfrom(args->connfd, args->buf, args->count, + MSG_TRUNC, &addr.gen, &addr_size); + if (r_ss < 0) { + *args->ret_size = 0; + *args->ret_errno = errno; goto end; + } + *args->ret_size = r_ss; + *args->ret_errno = 0; assert(addr.in.sin_family == AF_INET); if (args->ret_node) { - args->ret_node->octets[0] = (addr.in.sin_addr.s_addr >> 24) & 0xFF; - args->ret_node->octets[1] = (addr.in.sin_addr.s_addr >> 16) & 0xFF; - args->ret_node->octets[2] = (addr.in.sin_addr.s_addr >> 8) & 0xFF; - args->ret_node->octets[3] = (addr.in.sin_addr.s_addr >> 0) & 0xFF; + args->ret_node->octets[3] = (addr.in.sin_addr.s_addr >> 24) & 0xFF; + args->ret_node->octets[2] = (addr.in.sin_addr.s_addr >> 16) & 0xFF; + args->ret_node->octets[1] = (addr.in.sin_addr.s_addr >> 8) & 0xFF; + args->ret_node->octets[0] = (addr.in.sin_addr.s_addr >> 0) & 0xFF; } if (args->ret_port) { (*args->ret_port) = ntohs(addr.in.sin_port); } end: - if (*(args->ret_size) < 0) - *(args->ret_size) = hostnet_map_negerrno(-errno, OP_RECV); WAKE_COROUTINE(args); return NULL; } -static ssize_t hostnet_udp_recvfrom(struct hostnet_udp_conn *conn, void *buf, size_t count, - struct net_ip4_addr *ret_node, uint16_t *ret_port) { +size_t_or_error hostnet_udp_recvfrom(struct hostnet_udp_conn *conn, void *buf, size_t count, + struct net_ip4_addr *ret_node, uint16_t *ret_port) { assert(conn); - ssize_t ret; + size_t ret_size; + host_errno_t ret_errno; struct hostnet_pthread_recvfrom_args args = { .cr_thread = pthread_self(), .cr_coroutine = cr_getcid(), @@ -507,28 +569,34 @@ static ssize_t hostnet_udp_recvfrom(struct hostnet_udp_conn *conn, void *buf, si .buf = buf, .count = count, - .ret_size = &ret, + .ret_size = &ret_size, + .ret_errno = &ret_errno, .ret_node = ret_node, .ret_port = ret_port, }; if (conn->read_deadline_ns) { uint64_t now_ns = LO_CALL(bootclock, get_time_ns); if (conn->read_deadline_ns < now_ns) - return -NET_ERECV_TIMEOUT; + return ERROR_NEW_ERR(size_t, error_new(E_NET_ERECV_TIMEOUT)); args.timeout = ns_to_host_us_time(conn->read_deadline_ns-now_ns); } else { - args.timeout = (host_us_time_t){0}; + args.timeout = (host_us_time_t){}; } - if (RUN_PTHREAD(hostnet_pthread_recvfrom, &args)) - return -NET_ETHREAD; - return ret; + host_errno_t thread_errno = RUN_PTHREAD(hostnet_pthread_recvfrom, &args); + if (thread_errno) + return ERROR_NEW_ERR(size_t, errno2lm(thread_errno)); + if (ret_errno) + return ERROR_NEW_ERR(size_t, hostnet_error(ret_errno, OP_RECV)); + return ERROR_NEW_VAL(size_t, ret_size); } /* UDP close() ****************************************************************/ -static int hostnet_udp_close(struct hostnet_udp_conn *conn) { +error hostnet_udp_close(struct hostnet_udp_conn *conn) { assert(conn); - return hostnet_map_negerrno(close(conn->fd) ? -errno : 0, OP_NONE); + if (close(conn->fd)) + return hostnet_error(errno, OP_CLOSE); + return ERROR_NULL; } |