From ce247c82f40681b88549ff588ec0a4ea5f8b00ae Mon Sep 17 00:00:00 2001 From: Sergey Chernyshev Date: Wed, 24 Apr 2024 23:39:20 +0200 Subject: [PATCH] deps: update uvwasi to 0.0.19 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/49908 Reviewed-By: Tobias Nießen Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca --- graal-nodejs/deps/uvwasi/include/uvwasi.h | 11 +- graal-nodejs/deps/uvwasi/src/fd_table.c | 69 +++- graal-nodejs/deps/uvwasi/src/fd_table.h | 5 + graal-nodejs/deps/uvwasi/src/sync_helpers.c | 95 ++++++ graal-nodejs/deps/uvwasi/src/sync_helpers.h | 27 ++ graal-nodejs/deps/uvwasi/src/uvwasi.c | 320 ++++++++++++++++-- graal-nodejs/deps/uvwasi/src/wasi_rights.h | 5 +- .../maintaining/maintaining-dependencies.md | 6 +- 8 files changed, 491 insertions(+), 47 deletions(-) create mode 100644 graal-nodejs/deps/uvwasi/src/sync_helpers.c create mode 100644 graal-nodejs/deps/uvwasi/src/sync_helpers.h diff --git a/graal-nodejs/deps/uvwasi/include/uvwasi.h b/graal-nodejs/deps/uvwasi/include/uvwasi.h index d475d3e6751..a458cfe17da 100644 --- a/graal-nodejs/deps/uvwasi/include/uvwasi.h +++ b/graal-nodejs/deps/uvwasi/include/uvwasi.h @@ -5,12 +5,13 @@ extern "C" { #endif +#include "uv.h" #include "wasi_serdes.h" #include "wasi_types.h" #define UVWASI_VERSION_MAJOR 0 #define UVWASI_VERSION_MINOR 0 -#define UVWASI_VERSION_PATCH 18 +#define UVWASI_VERSION_PATCH 19 #define UVWASI_VERSION_HEX ((UVWASI_VERSION_MAJOR << 16) | \ (UVWASI_VERSION_MINOR << 8) | \ (UVWASI_VERSION_PATCH)) @@ -47,6 +48,7 @@ typedef struct uvwasi_s { char* env_buf; uvwasi_size_t env_buf_size; const uvwasi_mem_t* allocator; + uv_loop_t* loop; } uvwasi_t; typedef struct uvwasi_preopen_s { @@ -54,10 +56,17 @@ typedef struct uvwasi_preopen_s { const char* real_path; } uvwasi_preopen_t; +typedef struct uvwasi_preopen_socket_s { + const char* address; + int port; +} uvwasi_preopen_socket_t; + typedef struct uvwasi_options_s { uvwasi_size_t fd_table_size; uvwasi_size_t preopenc; uvwasi_preopen_t* preopens; + uvwasi_size_t preopen_socketc; + uvwasi_preopen_socket_t* preopen_sockets; uvwasi_size_t argc; const char** argv; const char** envp; diff --git a/graal-nodejs/deps/uvwasi/src/fd_table.c b/graal-nodejs/deps/uvwasi/src/fd_table.c index 7782f1ee43b..881d192ff3a 100644 --- a/graal-nodejs/deps/uvwasi/src/fd_table.c +++ b/graal-nodejs/deps/uvwasi/src/fd_table.c @@ -37,6 +37,7 @@ static uvwasi_errno_t uvwasi__insert_stdio(uvwasi_t* uvwasi, err = uvwasi_fd_table_insert(uvwasi, table, fd, + NULL, name, name, type, @@ -58,6 +59,7 @@ static uvwasi_errno_t uvwasi__insert_stdio(uvwasi_t* uvwasi, uvwasi_errno_t uvwasi_fd_table_insert(uvwasi_t* uvwasi, struct uvwasi_fd_table_t* table, uv_file fd, + uv_tcp_t* sock, const char* mapped_path, const char* real_path, uvwasi_filetype_t type, @@ -78,29 +80,40 @@ uvwasi_errno_t uvwasi_fd_table_insert(uvwasi_t* uvwasi, char* rp_copy; char* np_copy; - mp_len = strlen(mapped_path); - rp_len = strlen(real_path); + if (type != UVWASI_FILETYPE_SOCKET_STREAM) { + mp_len = strlen(mapped_path); + rp_len = strlen(real_path); + } else { + mp_len = 0; + rp_len = 0; + rp_copy = NULL; + mp_copy = NULL; + np_copy = NULL; + } + /* Reserve room for the mapped path, real path, and normalized mapped path. */ entry = (struct uvwasi_fd_wrap_t*) uvwasi__malloc(uvwasi, sizeof(*entry) + mp_len + mp_len + rp_len + 3); if (entry == NULL) return UVWASI_ENOMEM; - mp_copy = (char*)(entry + 1); - rp_copy = mp_copy + mp_len + 1; - np_copy = rp_copy + rp_len + 1; - memcpy(mp_copy, mapped_path, mp_len); - mp_copy[mp_len] = '\0'; - memcpy(rp_copy, real_path, rp_len); - rp_copy[rp_len] = '\0'; - - /* Calculate the normalized version of the mapped path, as it will be used for - any path calculations on this fd. Use the length of the mapped path as an - upper bound for the normalized path length. */ - err = uvwasi__normalize_path(mp_copy, mp_len, np_copy, mp_len); - if (err) { - uvwasi__free(uvwasi, entry); - goto exit; + if (type != UVWASI_FILETYPE_SOCKET_STREAM) { + mp_copy = (char*)(entry + 1); + rp_copy = mp_copy + mp_len + 1; + np_copy = rp_copy + rp_len + 1; + memcpy(mp_copy, mapped_path, mp_len); + mp_copy[mp_len] = '\0'; + memcpy(rp_copy, real_path, rp_len); + rp_copy[rp_len] = '\0'; + + /* Calculate the normalized version of the mapped path, as it will be used for + any path calculations on this fd. Use the length of the mapped path as an + upper bound for the normalized path length. */ + err = uvwasi__normalize_path(mp_copy, mp_len, np_copy, mp_len); + if (err) { + uvwasi__free(uvwasi, entry); + goto exit; + } } uv_rwlock_wrlock(&table->rwlock); @@ -150,6 +163,7 @@ uvwasi_errno_t uvwasi_fd_table_insert(uvwasi_t* uvwasi, entry->id = index; entry->fd = fd; + entry->sock = sock; entry->path = mp_copy; entry->real_path = rp_copy; entry->normalized_path = np_copy; @@ -280,6 +294,7 @@ uvwasi_errno_t uvwasi_fd_table_insert_preopen(uvwasi_t* uvwasi, return uvwasi_fd_table_insert(uvwasi, table, fd, + NULL, path, real_path, UVWASI_FILETYPE_DIRECTORY, @@ -290,6 +305,26 @@ uvwasi_errno_t uvwasi_fd_table_insert_preopen(uvwasi_t* uvwasi, } +uvwasi_errno_t uvwasi_fd_table_insert_preopen_socket(uvwasi_t* uvwasi, + struct uvwasi_fd_table_t* table, + uv_tcp_t* sock) { + if (table == NULL || sock == NULL) + return UVWASI_EINVAL; + + return uvwasi_fd_table_insert(uvwasi, + table, + -1, + sock, + NULL, + NULL, + UVWASI_FILETYPE_SOCKET_STREAM, + UVWASI__RIGHTS_SOCKET_BASE, + UVWASI__RIGHTS_SOCKET_INHERITING, + 1, + NULL); +} + + uvwasi_errno_t uvwasi_fd_table_get(struct uvwasi_fd_table_t* table, const uvwasi_fd_t id, struct uvwasi_fd_wrap_t** wrap, diff --git a/graal-nodejs/deps/uvwasi/src/fd_table.h b/graal-nodejs/deps/uvwasi/src/fd_table.h index 0755c2d17fd..9a7a825bc85 100644 --- a/graal-nodejs/deps/uvwasi/src/fd_table.h +++ b/graal-nodejs/deps/uvwasi/src/fd_table.h @@ -11,6 +11,7 @@ struct uvwasi_options_s; struct uvwasi_fd_wrap_t { uvwasi_fd_t id; uv_file fd; + uv_tcp_t* sock; char* path; char* real_path; char* normalized_path; @@ -35,6 +36,7 @@ void uvwasi_fd_table_free(struct uvwasi_s* uvwasi, uvwasi_errno_t uvwasi_fd_table_insert(struct uvwasi_s* uvwasi, struct uvwasi_fd_table_t* table, uv_file fd, + uv_tcp_t* sock, const char* mapped_path, const char* real_path, uvwasi_filetype_t type, @@ -47,6 +49,9 @@ uvwasi_errno_t uvwasi_fd_table_insert_preopen(struct uvwasi_s* uvwasi, const uv_file fd, const char* path, const char* real_path); +uvwasi_errno_t uvwasi_fd_table_insert_preopen_socket(struct uvwasi_s* uvwasi, + struct uvwasi_fd_table_t* table, + uv_tcp_t* sock); uvwasi_errno_t uvwasi_fd_table_get(struct uvwasi_fd_table_t* table, const uvwasi_fd_t id, struct uvwasi_fd_wrap_t** wrap, diff --git a/graal-nodejs/deps/uvwasi/src/sync_helpers.c b/graal-nodejs/deps/uvwasi/src/sync_helpers.c new file mode 100644 index 00000000000..c63a62b83d7 --- /dev/null +++ b/graal-nodejs/deps/uvwasi/src/sync_helpers.c @@ -0,0 +1,95 @@ +#include "uv.h" +#include "sync_helpers.h" +#include "uv_mapping.h" +#include "uvwasi_alloc.h" + +typedef struct free_handle_data_s { + uvwasi_t* uvwasi; + int done; +} free_handle_data_t; + +static void free_handle_cb(uv_handle_t* handle) { + free_handle_data_t* free_handle_data = uv_handle_get_data((uv_handle_t*) handle); + uvwasi__free(free_handle_data->uvwasi, handle); + free_handle_data->done = 1; +} + +int free_handle_sync(struct uvwasi_s* uvwasi, uv_handle_t* handle) { + free_handle_data_t free_handle_data = { uvwasi, 0 }; + uv_handle_set_data(handle, (void*) &free_handle_data); + uv_close(handle, free_handle_cb); + uv_loop_t* handle_loop = uv_handle_get_loop(handle); + while(!free_handle_data.done) { + if (uv_run(handle_loop, UV_RUN_ONCE) == 0) { + break; + } + } + return UVWASI_ESUCCESS; +} + +static void do_stream_shutdown(uv_shutdown_t* req, int status) { + shutdown_data_t* shutdown_data; + shutdown_data = uv_handle_get_data((uv_handle_t*) req->handle); + shutdown_data->status = status; + shutdown_data->done = 1; + } + +int shutdown_stream_sync(struct uvwasi_s* uvwasi, + uv_stream_t* stream, + shutdown_data_t* shutdown_data) { + uv_shutdown_t req; + uv_loop_t* stream_loop; + + shutdown_data->done = 0; + shutdown_data->status = 0; + stream_loop = uv_handle_get_loop((uv_handle_t*) stream); + + uv_handle_set_data((uv_handle_t*) stream, (void*) shutdown_data); + uv_shutdown(&req, stream, do_stream_shutdown); + while (!shutdown_data->done) { + if (uv_run(stream_loop, UV_RUN_ONCE) == 0) { + return UVWASI_ECANCELED; + } + } + return UVWASI_ESUCCESS; +} + +static void recv_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { + recv_data_t* recv_data; + recv_data = uv_handle_get_data(handle); + buf->base = recv_data->base; + buf->len = recv_data->len; +} + +void do_stream_recv(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { + recv_data_t* recv_data; + recv_data = uv_handle_get_data((uv_handle_t*) stream); + uv_read_stop(stream); + recv_data->nread = nread; + recv_data->done = 1; +} + +int read_stream_sync(struct uvwasi_s* uvwasi, + uv_stream_t* stream, + recv_data_t* recv_data) { + uv_loop_t* recv_loop; + int r; + + recv_data->nread = 0; + recv_data->done = 0; + recv_loop = uv_handle_get_loop((uv_handle_t*) stream); + + uv_handle_set_data((uv_handle_t*) stream, (void*) recv_data); + r = uv_read_start(stream, recv_alloc_cb, do_stream_recv); + if (r != 0) { + return uvwasi__translate_uv_error(r); + } + + while (!recv_data->done) { + if (uv_run(recv_loop, UV_RUN_ONCE) == 0) { + return UVWASI_ECANCELED; + } + } + + return UVWASI_ESUCCESS; +} diff --git a/graal-nodejs/deps/uvwasi/src/sync_helpers.h b/graal-nodejs/deps/uvwasi/src/sync_helpers.h new file mode 100644 index 00000000000..6ffe2cac133 --- /dev/null +++ b/graal-nodejs/deps/uvwasi/src/sync_helpers.h @@ -0,0 +1,27 @@ +#ifndef __UVWASI_SYNC_HELPERS_H__ +#define __UVWASI_SYNC_HELPERS_H__ + +struct uvwasi_s; + +typedef struct shutdown_data_s { + int status; + int done; +} shutdown_data_t; + +typedef struct recv_data_s { + char* base; + size_t len; + ssize_t nread; + int done; +} recv_data_t; + +int free_handle_sync(struct uvwasi_s* uvwasi, uv_handle_t* handle); + +int shutdown_stream_sync(struct uvwasi_s* uvwasi, + uv_stream_t* stream, + shutdown_data_t* shutdown_data); + +int read_stream_sync(struct uvwasi_s* uvwasi, + uv_stream_t* stream, + recv_data_t* recv_data); +#endif /* __UVWASI_SYNC_HELPERS_H__ */ diff --git a/graal-nodejs/deps/uvwasi/src/uvwasi.c b/graal-nodejs/deps/uvwasi/src/uvwasi.c index 9e7fc768166..e904b9f9293 100644 --- a/graal-nodejs/deps/uvwasi/src/uvwasi.c +++ b/graal-nodejs/deps/uvwasi/src/uvwasi.c @@ -25,6 +25,7 @@ #include "clocks.h" #include "path_resolver.h" #include "poll_oneoff.h" +#include "sync_helpers.h" #include "wasi_rights.h" #include "wasi_serdes.h" #include "debug.h" @@ -231,6 +232,13 @@ static uvwasi_errno_t uvwasi__setup_ciovs(const uvwasi_t* uvwasi, return UVWASI_ESUCCESS; } +typedef struct new_connection_data_s { + int done; +} new_connection_data_t; + +void on_new_connection(uv_stream_t *server, int status) { + // just do nothing +} uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, const uvwasi_options_t* options) { uv_fs_t realpath_req; @@ -243,11 +251,16 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, const uvwasi_options_t* options) { uvwasi_size_t env_buf_size; uvwasi_size_t i; int r; + struct sockaddr_in addr; if (uvwasi == NULL || options == NULL || options->fd_table_size == 0) return UVWASI_EINVAL; + // loop is only needed if there were pre-open sockets + uvwasi->loop = NULL; + uvwasi->allocator = options->allocator; + if (uvwasi->allocator == NULL) uvwasi->allocator = &default_allocator; @@ -328,6 +341,14 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, const uvwasi_options_t* options) { } } + for (i = 0; i < options->preopen_socketc; ++i) { + if (options->preopen_sockets[i].address == NULL || + options->preopen_sockets[i].port > 65535) { + err = UVWASI_EINVAL; + goto exit; + } + } + err = uvwasi_fd_table_init(uvwasi, options); if (err != UVWASI_ESUCCESS) goto exit; @@ -363,6 +384,36 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, const uvwasi_options_t* options) { goto exit; } + if (options->preopen_socketc > 0) { + uvwasi->loop = uvwasi__malloc(uvwasi, sizeof(uv_loop_t)); + r = uv_loop_init(uvwasi->loop); + if (r != 0) { + err = uvwasi__translate_uv_error(r); + goto exit; + } + } + + for (i = 0; i < options->preopen_socketc; ++i) { + uv_tcp_t* socket = (uv_tcp_t*) malloc(sizeof(uv_tcp_t)); + uv_tcp_init(uvwasi->loop, socket); + + uv_ip4_addr(options->preopen_sockets[i].address, options->preopen_sockets[i].port, &addr); + + uv_tcp_bind(socket, (const struct sockaddr*)&addr, 0); + r = uv_listen((uv_stream_t*) socket, 128, on_new_connection); + if (r != 0) { + err = uvwasi__translate_uv_error(r); + goto exit; + } + + err = uvwasi_fd_table_insert_preopen_socket(uvwasi, + uvwasi->fds, + socket); + + if (err != UVWASI_ESUCCESS) + goto exit; + } + return UVWASI_ESUCCESS; exit: @@ -380,6 +431,12 @@ void uvwasi_destroy(uvwasi_t* uvwasi) { uvwasi__free(uvwasi, uvwasi->argv); uvwasi__free(uvwasi, uvwasi->env_buf); uvwasi__free(uvwasi, uvwasi->env); + if (uvwasi->loop != NULL) { + uv_stop(uvwasi->loop); + uv_loop_close(uvwasi->loop); + uvwasi__free(uvwasi, uvwasi->loop); + uvwasi->loop = NULL; + } uvwasi->fds = NULL; uvwasi->argv_buf = NULL; uvwasi->argv = NULL; @@ -401,6 +458,8 @@ void uvwasi_options_init(uvwasi_options_t* options) { options->envp = NULL; options->preopenc = 0; options->preopens = NULL; + options->preopen_socketc = 0; + options->preopen_sockets = NULL; options->allocator = NULL; } @@ -694,10 +753,9 @@ uvwasi_errno_t uvwasi_fd_allocate(uvwasi_t* uvwasi, return err; } - uvwasi_errno_t uvwasi_fd_close(uvwasi_t* uvwasi, uvwasi_fd_t fd) { struct uvwasi_fd_wrap_t* wrap; - uvwasi_errno_t err; + uvwasi_errno_t err = 0; uv_fs_t req; int r; @@ -712,9 +770,18 @@ uvwasi_errno_t uvwasi_fd_close(uvwasi_t* uvwasi, uvwasi_fd_t fd) { if (err != UVWASI_ESUCCESS) goto exit; - r = uv_fs_close(NULL, &req, wrap->fd, NULL); - uv_mutex_unlock(&wrap->mutex); - uv_fs_req_cleanup(&req); + if (wrap->sock == NULL) { + r = uv_fs_close(NULL, &req, wrap->fd, NULL); + uv_mutex_unlock(&wrap->mutex); + uv_fs_req_cleanup(&req); + } else { + r = 0; + err = free_handle_sync(uvwasi, (uv_handle_t*) wrap->sock); + uv_mutex_unlock(&wrap->mutex); + if (err != UVWASI_ESUCCESS) { + goto exit; + } + } if (r != 0) { err = uvwasi__translate_uv_error(r); @@ -1997,6 +2064,7 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi, err = uvwasi_fd_table_insert(uvwasi, uvwasi->fds, r, + NULL, resolved_path, resolved_path, filetype, @@ -2520,7 +2588,6 @@ uvwasi_errno_t uvwasi_sched_yield(uvwasi_t* uvwasi) { return UVWASI_ESUCCESS; } - uvwasi_errno_t uvwasi_sock_recv(uvwasi_t* uvwasi, uvwasi_fd_t sock, const uvwasi_iovec_t* ri_data, @@ -2528,10 +2595,50 @@ uvwasi_errno_t uvwasi_sock_recv(uvwasi_t* uvwasi, uvwasi_riflags_t ri_flags, uvwasi_size_t* ro_datalen, uvwasi_roflags_t* ro_flags) { - /* TODO(cjihrig): Waiting to implement, pending - https://github.com/WebAssembly/WASI/issues/4 */ - UVWASI_DEBUG("uvwasi_sock_recv(uvwasi=%p, unimplemented)\n", uvwasi); - return UVWASI_ENOTSUP; + struct uvwasi_fd_wrap_t* wrap; + uvwasi_errno_t err = 0; + recv_data_t recv_data; + + UVWASI_DEBUG("uvwasi_sock_recv(uvwasi=%p, sock=%d, ri_data=%p, " + "ri_data_len=%d, ri_flags=%d, ro_datalen=%p, ro_flags=%p)\n", + uvwasi, + sock, + ri_data, + ri_data_len, + ri_flags, + ro_datalen, + ro_flags); + + if (uvwasi == NULL || ri_data == NULL || ro_datalen == NULL || ro_flags == NULL) + return UVWASI_EINVAL; + + if (ri_flags != 0) + return UVWASI_ENOTSUP; + + err = uvwasi_fd_table_get(uvwasi->fds, + sock, + &wrap, + UVWASI__RIGHTS_SOCKET_BASE, + 0); + if (err != UVWASI_ESUCCESS) + return err; + + recv_data.base = ri_data->buf; + recv_data.len = ri_data->buf_len; + err = read_stream_sync(uvwasi, (uv_stream_t*) wrap->sock, &recv_data); + uv_mutex_unlock(&wrap->mutex); + if (err != 0) { + return err; + } + + if (recv_data.nread == 0) { + return UVWASI_EAGAIN; + } else if (recv_data.nread < 0) { + return uvwasi__translate_uv_error(recv_data.nread); + } + + *ro_datalen = recv_data.nread; + return UVWASI_ESUCCESS; } @@ -2541,30 +2648,195 @@ uvwasi_errno_t uvwasi_sock_send(uvwasi_t* uvwasi, uvwasi_size_t si_data_len, uvwasi_siflags_t si_flags, uvwasi_size_t* so_datalen) { - /* TODO(cjihrig): Waiting to implement, pending - https://github.com/WebAssembly/WASI/issues/4 */ - UVWASI_DEBUG("uvwasi_sock_send(uvwasi=%p, unimplemented)\n", uvwasi); - return UVWASI_ENOTSUP; -} + struct uvwasi_fd_wrap_t* wrap; + uvwasi_errno_t err = 0; + uv_buf_t* bufs; + int r = 0; + + UVWASI_DEBUG("uvwasi_sock_send(uvwasi=%p, sock=%d, si_data=%p, " + "si_data_len=%d, si_flags=%d, so_datalen=%p)\n", + uvwasi, + sock, + si_data, + si_data_len, + si_flags, + so_datalen); + + if (uvwasi == NULL || si_data == NULL || so_datalen == NULL || + si_flags != 0) + return UVWASI_EINVAL; + + err = uvwasi_fd_table_get(uvwasi->fds, + sock, + &wrap, + UVWASI__RIGHTS_SOCKET_BASE, + 0); + if (err != UVWASI_ESUCCESS) + return err; + + err = uvwasi__setup_ciovs(uvwasi, &bufs, si_data, si_data_len); + if (err != UVWASI_ESUCCESS) { + uv_mutex_unlock(&wrap->mutex); + return err; + } + + r = uv_try_write((uv_stream_t*) wrap->sock, bufs, si_data_len); + uvwasi__free(uvwasi, bufs); + uv_mutex_unlock(&wrap->mutex); + if (r < 0) + return uvwasi__translate_uv_error(r); + + *so_datalen = (uvwasi_size_t) r; + return UVWASI_ESUCCESS; +} uvwasi_errno_t uvwasi_sock_shutdown(uvwasi_t* uvwasi, uvwasi_fd_t sock, uvwasi_sdflags_t how) { - /* TODO(cjihrig): Waiting to implement, pending - https://github.com/WebAssembly/WASI/issues/4 */ - UVWASI_DEBUG("uvwasi_sock_shutdown(uvwasi=%p, unimplemented)\n", uvwasi); - return UVWASI_ENOTSUP; + struct uvwasi_fd_wrap_t* wrap; + uvwasi_errno_t err = 0; + shutdown_data_t shutdown_data; + + if (how & ~UVWASI_SHUT_WR) + return UVWASI_ENOTSUP; + + UVWASI_DEBUG("uvwasi_sock_shutdown(uvwasi=%p, sock=%d, how=%d)\n", + uvwasi, + sock, + how); + + if (uvwasi == NULL) + return UVWASI_EINVAL; + + err = uvwasi_fd_table_get(uvwasi->fds, + sock, + &wrap, + UVWASI__RIGHTS_SOCKET_BASE, + 0); + if (err != UVWASI_ESUCCESS) + return err; + + if (how & UVWASI_SHUT_WR) { + err = shutdown_stream_sync(uvwasi, (uv_stream_t*) wrap->sock, &shutdown_data); + if (err != UVWASI_ESUCCESS) { + uv_mutex_unlock(&wrap->mutex); + return err; + } + } + + uv_mutex_unlock(&wrap->mutex); + + if (shutdown_data.status != 0) + return uvwasi__translate_uv_error(shutdown_data.status); + + return UVWASI_ESUCCESS; } uvwasi_errno_t uvwasi_sock_accept(uvwasi_t* uvwasi, uvwasi_fd_t sock, uvwasi_fdflags_t flags, - uvwasi_fd_t* fd) { - /* TODO(mhdawson): Needs implementation */ - UVWASI_DEBUG("uvwasi_sock_accept(uvwasi=%p, unimplemented)\n", uvwasi); - return UVWASI_ENOTSUP; -}; + uvwasi_fd_t* connect_sock) { + struct uvwasi_fd_wrap_t* wrap; + struct uvwasi_fd_wrap_t* connected_wrap; + uvwasi_errno_t err = 0; + uv_loop_t* sock_loop = NULL; + int r = 0; + + UVWASI_DEBUG("uvwasi_sock_accept(uvwasi=%p, sock=%d, flags=%d, " + "connect_sock=%p)\n", + uvwasi, + sock, + flags, + connect_sock); + + if (uvwasi == NULL || connect_sock == NULL) + return UVWASI_EINVAL; + + if (flags & ~UVWASI_FDFLAG_NONBLOCK) + return UVWASI_ENOTSUP; + + err = uvwasi_fd_table_get(uvwasi->fds, + sock, + &wrap, + UVWASI__RIGHTS_SOCKET_BASE, + 0); + if (err != UVWASI_ESUCCESS) + return err; + + sock_loop = uv_handle_get_loop((uv_handle_t*) wrap->sock); + uv_tcp_t* uv_connect_sock = (uv_tcp_t*) uvwasi__malloc(uvwasi, sizeof(uv_tcp_t)); + uv_tcp_init(sock_loop, uv_connect_sock); + + r = uv_accept((uv_stream_t*) wrap->sock, (uv_stream_t*) uv_connect_sock); + if (r != 0) { + if (r == UV_EAGAIN) { + // if not blocking then just return as we have to wait for a connection + if (flags & UVWASI_FDFLAG_NONBLOCK) { + err = free_handle_sync(uvwasi, (uv_handle_t*) uv_connect_sock); + uv_mutex_unlock(&wrap->mutex); + if (err != UVWASI_ESUCCESS) { + return err; + } + return UVWASI_EAGAIN; + } + } else { + err = uvwasi__translate_uv_error(r); + goto close_sock_and_error_exit; + } + + // request was blocking and we have no connection yet. run + // the loop until a connection comes in + while (1) { + err = 0; + if (uv_run(sock_loop, UV_RUN_ONCE) == 0) { + err = UVWASI_ECONNABORTED; + goto close_sock_and_error_exit; + } + + int r = uv_accept((uv_stream_t*) wrap->sock, (uv_stream_t*) uv_connect_sock); + if (r == UV_EAGAIN) { + // still no connection or error so run the loop again + continue; + } + + if (r != 0) { + // An error occurred accepting the connection. Break out of the loop and + // report an error. + err = uvwasi__translate_uv_error(r); + goto close_sock_and_error_exit; + } + + // if we get here a new connection was successfully accepted + break; + } + } + + err = uvwasi_fd_table_insert(uvwasi, + uvwasi->fds, + -1, + uv_connect_sock, + NULL, + NULL, + UVWASI_FILETYPE_SOCKET_STREAM, + UVWASI__RIGHTS_SOCKET_BASE, + UVWASI__RIGHTS_SOCKET_INHERITING, + 1, + &connected_wrap); + + if (err != UVWASI_ESUCCESS) + goto close_sock_and_error_exit; + + *connect_sock = connected_wrap->id; + uv_mutex_unlock(&wrap->mutex); + uv_mutex_unlock(&connected_wrap->mutex); + return UVWASI_ESUCCESS; + +close_sock_and_error_exit: + uvwasi__free(uvwasi, uv_connect_sock); + uv_mutex_unlock(&wrap->mutex); + return err; +} const char* uvwasi_embedder_err_code_to_string(uvwasi_errno_t code) { diff --git a/graal-nodejs/deps/uvwasi/src/wasi_rights.h b/graal-nodejs/deps/uvwasi/src/wasi_rights.h index 09009b39889..54ac7d7072b 100644 --- a/graal-nodejs/deps/uvwasi/src/wasi_rights.h +++ b/graal-nodejs/deps/uvwasi/src/wasi_rights.h @@ -84,8 +84,9 @@ UVWASI_RIGHT_FD_WRITE | \ UVWASI_RIGHT_FD_FILESTAT_GET | \ UVWASI_RIGHT_POLL_FD_READWRITE | \ - UVWASI_RIGHT_SOCK_SHUTDOWN) -#define UVWASI__RIGHTS_SOCKET_INHERITING UVWASI__RIGHTS_ALL; + UVWASI_RIGHT_SOCK_SHUTDOWN | \ + UVWASI_RIGHT_SOCK_ACCEPT) +#define UVWASI__RIGHTS_SOCKET_INHERITING UVWASI__RIGHTS_ALL #define UVWASI__RIGHTS_TTY_BASE (UVWASI_RIGHT_FD_READ | \ UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ diff --git a/graal-nodejs/doc/contributing/maintaining/maintaining-dependencies.md b/graal-nodejs/doc/contributing/maintaining/maintaining-dependencies.md index 20b10492597..f1e08619373 100644 --- a/graal-nodejs/doc/contributing/maintaining/maintaining-dependencies.md +++ b/graal-nodejs/doc/contributing/maintaining/maintaining-dependencies.md @@ -28,7 +28,7 @@ This a list of all the dependencies: * [simdutf 3.2.18][] * [undici 5.26.4][] * [uv][] -* [uvwasi][] +* [uvwasi 0.0.19][] * [V8][] * [zlib][] @@ -290,7 +290,7 @@ The [libuv](https://github.com/libuv/libuv) dependency is a multi-platform support library with a focus on asynchronous I/O. It was primarily developed for use by Node.js. -### uvwasi +### uvwasi 0.0.19 The [uvwasi](https://github.com/nodejs/uvwasi) dependency implements the WASI system call API, so that WebAssembly runtimes can easily @@ -339,6 +339,6 @@ performance improvements not currently available in standard zlib. [undici 5.26.4]: #undici-5264 [update-openssl-action]: ../../../.github/workflows/update-openssl.yml [uv]: #uv -[uvwasi]: #uvwasi +[uvwasi 0.0.19]: #uvwasi-0019 [v8]: #v8 [zlib]: #zlib