From 8d537440533cfc290e33c7bcbf181ab414dd1850 Mon Sep 17 00:00:00 2001 From: Sadhbh Code Date: Thu, 4 Jun 2026 21:59:26 +0100 Subject: [PATCH 1/3] Wasix-LibC supports SOL_SOCKET + SO_KEEPALIVE, however does not support additional options such as TCP_KEEPIDLE, TCP_KEEPINTVL, or TCP_KEEPCNT - so we disable them --- src/unix/tcp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/unix/tcp.c b/src/unix/tcp.c index 852c189c7a7..88f1f1df87a 100644 --- a/src/unix/tcp.c +++ b/src/unix/tcp.c @@ -489,6 +489,10 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay) { if (delay < 1) return UV_EINVAL; +#if defined(__wasi__) || defined(__wasm32__) + return 0; +#endif + #ifdef __sun /* The implementation of TCP keep-alive on Solaris/SmartOS is a bit unusual * compared to other Unix-like systems. From 5539194c8f9e751e4a7da94cd4fb69722736e9ae Mon Sep 17 00:00:00 2001 From: Sadhbh Code Date: Thu, 4 Jun 2026 22:55:52 +0100 Subject: [PATCH 2/3] Skip creating socket with SOCK_NONBLOCK | SOCK_CLOEXEC flags on wasi --- src/unix/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unix/core.c b/src/unix/core.c index 0fe2d1799cb..5ff225513e3 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -522,7 +522,7 @@ int uv__socket(int domain, int type, int protocol) { int sockfd; int err; -#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) +#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) && !defined(__wasi__) && !defined(__wasm32__) sockfd = socket(domain, type | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol); if (sockfd != -1) return sockfd; From 759cdf536c4a91e88a5b5b49f733514e4e6f8651 Mon Sep 17 00:00:00 2001 From: Sadhbh Code Date: Fri, 5 Jun 2026 19:31:18 +0100 Subject: [PATCH 3/3] =?UTF-8?q?multicast=20TTL/loop/interface=20shims=20fo?= =?UTF-8?q?r=20WASIX,=20plus=20WASIX=20UDP=20disconnect=20avoids=20the=20u?= =?UTF-8?q?nsupported=20AF=5FUNSPEC=20connect()=20trick.=20WASIX=20connect?= =?UTF-8?q?ed-state=20checks=20now=20trust=20libuv=E2=80=99s=20handle=20fl?= =?UTF-8?q?ag.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/unix/udp.c | 38 ++++++++++++++++++++++++++++++++++++++ src/uv-common.c | 5 +++++ 2 files changed, 43 insertions(+) diff --git a/src/unix/udp.c b/src/unix/udp.c index c4a3559d61e..2dc138e47f3 100644 --- a/src/unix/udp.c +++ b/src/unix/udp.c @@ -530,6 +530,10 @@ int uv__udp_connect(uv_udp_t* handle, * if (addr->sa_family == AF_UNSPEC) sodisconnect(so); */ int uv__udp_disconnect(uv_udp_t* handle) { +#if defined(__wasi__) + handle->flags &= ~UV_HANDLE_UDP_CONNECTED; + return 0; +#else int r; #if defined(__MVS__) struct sockaddr_storage addr; @@ -570,6 +574,7 @@ int uv__udp_disconnect(uv_udp_t* handle) { handle->flags &= ~UV_HANDLE_UDP_CONNECTED; return 0; +#endif } int uv__udp_send(uv_udp_send_t* req, @@ -1087,6 +1092,15 @@ int uv_udp_set_ttl(uv_udp_t* handle, int ttl) { int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) { + if (ttl < 1 || ttl > 255) + return UV_EINVAL; + if (handle->io_watcher.fd == -1) + return UV_EBADF; + +#if defined(__wasi__) + return 0; +#endif + /* * On Solaris and derivatives such as SmartOS, the length of socket options * is sizeof(int) for IPV6_MULTICAST_HOPS and sizeof(char) for @@ -1112,6 +1126,13 @@ int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) { int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) { + if (handle->io_watcher.fd == -1) + return UV_EBADF; + +#if defined(__wasi__) + return 0; +#endif + /* * On Solaris and derivatives such as SmartOS, the length of socket options * is sizeof(int) for IPV6_MULTICAST_LOOP and sizeof(char) for @@ -1140,6 +1161,9 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) struct sockaddr_in* addr4; struct sockaddr_in6* addr6; + if (handle->io_watcher.fd == -1) + return UV_EBADF; + addr4 = (struct sockaddr_in*) &addr_st; addr6 = (struct sockaddr_in6*) &addr_st; @@ -1160,6 +1184,20 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) return UV_EINVAL; } +#if defined(__wasi__) + if ((handle->flags & UV_HANDLE_IPV6) && addr_st.ss_family == AF_INET) + return UV_EINVAL; + if (!(handle->flags & UV_HANDLE_IPV6) && addr_st.ss_family == AF_INET6) + return UV_EINVAL; + if (addr_st.ss_family == AF_INET && + IN_MULTICAST(ntohl(addr4->sin_addr.s_addr))) { + return UV_EINVAL; + } + if (addr_st.ss_family == AF_INET6 && IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr)) + return UV_EINVAL; + return 0; +#endif + if (addr_st.ss_family == AF_INET) { if (setsockopt(handle->io_watcher.fd, IPPROTO_IP, diff --git a/src/uv-common.c b/src/uv-common.c index 12b88f9b35f..807b99a2130 100644 --- a/src/uv-common.c +++ b/src/uv-common.c @@ -443,6 +443,10 @@ int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr) { int uv__udp_is_connected(uv_udp_t* handle) { +#if defined(__wasi__) + return handle->type == UV_UDP && + (handle->flags & UV_HANDLE_UDP_CONNECTED) != 0; +#else struct sockaddr_storage addr; int addrlen; if (handle->type != UV_UDP) @@ -453,6 +457,7 @@ int uv__udp_is_connected(uv_udp_t* handle) { return 0; return addrlen > 0; +#endif }