diff --git a/libc-bottom-half/cloudlibc/src/libc/fcntl/fcntl.c b/libc-bottom-half/cloudlibc/src/libc/fcntl/fcntl.c index 55ce46bbd..da9051a88 100644 --- a/libc-bottom-half/cloudlibc/src/libc/fcntl/fcntl.c +++ b/libc-bottom-half/cloudlibc/src/libc/fcntl/fcntl.c @@ -13,7 +13,7 @@ #endif int fcntl(int fildes, int cmd, ...) { -#ifdef __wasip2__ +#if defined(__wasip2__) || defined(__wasip3__) descriptor_table_entry_t *entry = descriptor_table_get_ref(fildes); if (entry == NULL) return -1; @@ -51,16 +51,12 @@ int fcntl(int fildes, int cmd, ...) { oflags |= O_SEARCH; } return oflags; -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) if (!entry->vtable->fcntl_getfl) { errno = EINVAL; return -1; } return entry->vtable->fcntl_getfl(entry->data); -#elif defined(__wasip3__) - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unknown WASI version" #endif @@ -80,16 +76,12 @@ int fcntl(int fildes, int cmd, ...) { errno = error; return -1; } -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) if (!entry->vtable->fcntl_setfl) { errno = EINVAL; return -1; } return entry->vtable->fcntl_setfl(entry->data, flags); -#elif defined(__wasip3__) - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unknown WASI version" #endif diff --git a/libc-bottom-half/cloudlibc/src/libc/poll/poll.c b/libc-bottom-half/cloudlibc/src/libc/poll/poll.c index 22567edb6..a09b2d3e2 100644 --- a/libc-bottom-half/cloudlibc/src/libc/poll/poll.c +++ b/libc-bottom-half/cloudlibc/src/libc/poll/poll.c @@ -287,8 +287,11 @@ static int poll_impl(struct pollfd *fds, size_t nfds, int timeout) { #elif defined(__wasip3__) +#include + static int poll_impl(struct pollfd *fds, size_t nfds, int timeout) { - // TODO(wasip3) + // TODO(wasip3): `abort()` is here temporarily to avoid timeouts in tests + abort(); errno = ENOTSUP; return -1; } diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/ioctl/ioctl.c b/libc-bottom-half/cloudlibc/src/libc/sys/ioctl/ioctl.c index 7b78d3224..bc360249e 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/ioctl/ioctl.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/ioctl/ioctl.c @@ -89,7 +89,7 @@ int ioctl(int fildes, int request, ...) { return -1; } return 0; -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) descriptor_table_entry_t *entry = descriptor_table_get_ref(fildes); va_list ap; va_start(ap, request); @@ -101,10 +101,6 @@ int ioctl(int fildes, int request, ...) { return -1; } return entry->vtable->set_blocking(entry->data, blocking); -#elif defined(__wasip3__) - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unknown WASI version" #endif diff --git a/libc-bottom-half/sources/wasip3_tcp.c b/libc-bottom-half/sources/wasip3_tcp.c index 5dda276dd..8f6e5ecec 100644 --- a/libc-bottom-half/sources/wasip3_tcp.c +++ b/libc-bottom-half/sources/wasip3_tcp.c @@ -3,10 +3,13 @@ #ifdef __wasip3__ #include +#include #include #include #include +static descriptor_vtable_t tcp_vtable; + static void tcp_free(void *data) { tcp_socket_t *tcp = (tcp_socket_t *)data; @@ -15,12 +18,6 @@ static void tcp_free(void *data) { free(tcp); } -static descriptor_vtable_t tcp_vtable = { - .free = tcp_free, - .getsockopt = __wasilibc_tcp_getsockopt, - .setsockopt = __wasilibc_tcp_setsockopt, -}; - static int tcp_add(sockets_own_tcp_socket_t socket, sockets_ip_address_family_t family, bool blocking, tcp_socket_t **out) { @@ -49,4 +46,41 @@ int __wasilibc_add_tcp_socket(sockets_own_tcp_socket_t socket, return tcp_add(socket, family, blocking, NULL); } +static int tcp_set_blocking(void *data, bool blocking) { + tcp_socket_t *tcp = (tcp_socket_t *)data; + tcp->blocking = blocking; + return 0; +} + +static int tcp_fcntl_getfl(void *data) { + tcp_socket_t *socket = (tcp_socket_t *)data; + int flags = 0; + if (!socket->blocking) { + flags |= O_NONBLOCK; + } + return flags; +} + +static int tcp_fcntl_setfl(void *data, int flags) { + tcp_socket_t *socket = (tcp_socket_t *)data; + if (flags & O_NONBLOCK) { + socket->blocking = false; + } else { + socket->blocking = true; + } + return 0; +} + +static descriptor_vtable_t tcp_vtable = { + .free = tcp_free, + + .set_blocking = tcp_set_blocking, + + .getsockopt = __wasilibc_tcp_getsockopt, + .setsockopt = __wasilibc_tcp_setsockopt, + + .fcntl_getfl = tcp_fcntl_getfl, + .fcntl_setfl = tcp_fcntl_setfl, +}; + #endif // __wasip3__ diff --git a/libc-bottom-half/sources/wasip3_udp.c b/libc-bottom-half/sources/wasip3_udp.c index bd696e65a..ab0600712 100644 --- a/libc-bottom-half/sources/wasip3_udp.c +++ b/libc-bottom-half/sources/wasip3_udp.c @@ -1,13 +1,138 @@ -#include #include #ifdef __wasip3__ -int __wasilibc_add_udp_socket(sockets_own_tcp_socket_t socket, +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + int dummy; +} udp_socket_state_unbound_t; +typedef struct { + int dummy; +} udp_socket_state_bound_t; + +typedef struct { + enum { + UDP_SOCKET_STATE_UNBOUND, + UDP_SOCKET_STATE_BOUND, + } tag; + union { + udp_socket_state_unbound_t unbound; + udp_socket_state_bound_t bound; + }; +} udp_socket_state_t; + +typedef struct { + sockets_own_udp_socket_t socket; + bool blocking; + sockets_ip_address_family_t family; + udp_socket_state_t state; +} udp_socket_t; + +static descriptor_vtable_t udp_vtable; + +int __wasilibc_add_udp_socket(sockets_own_udp_socket_t socket, sockets_ip_address_family_t family, bool blocking) { - // TODO(wasip3) - errno = ENOTSUP; - return -1; + udp_socket_t *udp = calloc(1, sizeof(udp_socket_t)); + if (!udp) { + sockets_udp_socket_drop_own(socket); + errno = ENOMEM; + return -1; + } + udp->state.tag = UDP_SOCKET_STATE_UNBOUND; + udp->socket = socket; + udp->family = family; + udp->blocking = blocking; + + descriptor_table_entry_t entry; + entry.vtable = &udp_vtable; + entry.data = udp; + return descriptor_table_insert(entry); +} + +static void udp_free(void *data) { + udp_socket_t *udp = (udp_socket_t *)data; + + sockets_udp_socket_drop_own(udp->socket); + + free(udp); +} + +static int udp_set_blocking(void *data, bool blocking) { + udp_socket_t *udp = (udp_socket_t *)data; + udp->blocking = blocking; + return 0; +} + +static int udp_fstat(void *data, struct stat *buf) { + udp_socket_t *udp = (udp_socket_t *)data; + memset(buf, 0, sizeof(struct stat)); + buf->st_mode = S_IFSOCK; + return 0; +} + +static int udp_bind(void *data, const struct sockaddr *addr, + socklen_t addrlen) { + udp_socket_t *socket = (udp_socket_t *)data; + sockets_ip_socket_address_t local_address; + if (__wasilibc_sockaddr_to_wasi(socket->family, addr, addrlen, + &local_address) < 0) + return -1; + if (socket->state.tag != UDP_SOCKET_STATE_UNBOUND) { + errno = EINVAL; + return -1; + } + + sockets_error_code_t error; + sockets_borrow_udp_socket_t socket_borrow = + sockets_borrow_udp_socket(socket->socket); + + if (!sockets_method_udp_socket_bind(socket_borrow, &local_address, &error)) { + return __wasilibc_socket_error_to_errno(error); + } + + // Bind successful. + socket->state.tag = UDP_SOCKET_STATE_BOUND; + return 0; +} + +static int udp_fcntl_getfl(void *data) { + udp_socket_t *socket = (udp_socket_t *)data; + int flags = 0; + if (!socket->blocking) { + flags |= O_NONBLOCK; + } + return flags; } + +static int udp_fcntl_setfl(void *data, int flags) { + udp_socket_t *socket = (udp_socket_t *)data; + if (flags & O_NONBLOCK) { + socket->blocking = false; + } else { + socket->blocking = true; + } + return 0; +} + +static descriptor_vtable_t udp_vtable = { + .free = udp_free, + + .set_blocking = udp_set_blocking, + .fstat = udp_fstat, + + .bind = udp_bind, + + .fcntl_getfl = udp_fcntl_getfl, + .fcntl_setfl = udp_fcntl_setfl, +}; + #endif // __wasip3__ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bb51b2c05..33ca27e3d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -317,7 +317,7 @@ if (NOT (WASI STREQUAL "p1")) add_wasilibc_test(sockets-nonblocking-udp.c NETWORK FAILP3) add_wasilibc_test(sockets-nonblocking-multiple.c NETWORK FAILP3) add_wasilibc_test(sockets-nonblocking-udp-multiple.c NETWORK FAILP3) - add_wasilibc_test(sockets-fcntl.c NETWORK FAILP3) + add_wasilibc_test(sockets-fcntl.c NETWORK) # TODO: flaky tests # add_wasilibc_test(sockets-nonblocking.c NETWORK)