Skip to content

Commit

Permalink
Implement a simple socket example
Browse files Browse the repository at this point in the history
By compile with *extension*, avoid patching wasi-libc

[skip ci]
  • Loading branch information
lum1n0us committed Dec 30, 2021
1 parent 20a1973 commit 862fa16
Show file tree
Hide file tree
Showing 14 changed files with 2,675 additions and 44 deletions.
277 changes: 236 additions & 41 deletions core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include "bh_platform.h"
#include "wasm_export.h"

extern __wasi_errno_t
convert_errno(int error);

void
wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception);

Expand Down Expand Up @@ -986,6 +989,136 @@ wasi_random_get(wasm_exec_env_t exec_env, void *buf, uint32 buf_len)
return wasmtime_ssp_random_get(buf, buf_len);
}

inline static int
wasi_sockaddr_to_sockaddr(const wasi_sockaddr_t *addr, wasi_socklen_t addrlen,
struct sockaddr *out)
{
if (addr->sa_family != __WASI_AF_INET) {
return __WASI_EAFNOSUPPORT;
}

memcpy(out, addr, addrlen);
out->sa_family = AF_INET;
return __WASI_ESUCCESS;
}

inline static void
sockaddr_to_wasi_sockaddr(const struct sockaddr *addr, socklen_t addrlen,
__wasi_sockaddr_t *out)
{
bh_assert(addrlen <= sizeof(__wasi_sockaddr_t));
memcpy(out, addr, addrlen);
out->sa_family = __WASI_AF_INET;
}

static wasi_errno_t
wasi_sock_accept(wasm_exec_env_t exec_env, wasi_fd_t sockfd,
wasi_sockaddr_t *wasi_addr, wasi_socklen_t *wasi_addrlen,
wasi_fd_t *ret_new_socket)
{
struct sockaddr addr = { 0 };
int new_fd;
socklen_t addrlen;
wasi_errno_t error;

if (!wasi_addr || !wasi_addrlen) {
return __WASI_EINVAL;
}

error = wasi_sockaddr_to_sockaddr(wasi_addr, *wasi_addrlen, &addr);
if (error != __WASI_ESUCCESS) {
return error;
}

addrlen = *wasi_addrlen;
new_fd = accept(sockfd, &addr, &addrlen);
if (new_fd < 0) {
return convert_errno(errno);
}

sockaddr_to_wasi_sockaddr(&addr, addrlen, wasi_addr);
*wasi_addrlen = addrlen;
*ret_new_socket = new_fd;
return __WASI_ESUCCESS;
}

static wasi_errno_t
wasi_sock_bind(wasm_exec_env_t exec_env, wasi_fd_t sockfd,
const wasi_sockaddr_t *wasi_addr, wasi_socklen_t addrlen)
{
struct sockaddr addr = { 0 };
wasi_errno_t error;

if (!wasi_addr || !addrlen) {
return __WASI_EINVAL;
}

error = wasi_sockaddr_to_sockaddr(wasi_addr, addrlen, &addr);
if (error != __WASI_ESUCCESS) {
return error;
}

if (bind(sockfd, &addr, addrlen) < 0) {
return convert_errno(errno);
}

return __WASI_ESUCCESS;
}

static wasi_errno_t
wasi_sock_connect(wasm_exec_env_t exec_env, wasi_fd_t sockfd,
const wasi_sockaddr_t *wasi_addr, wasi_socklen_t addrlen)
{
struct sockaddr addr = { 0 };
wasi_errno_t error;

if (!wasi_addr || !addrlen) {
return __WASI_EINVAL;
}

error = wasi_sockaddr_to_sockaddr(wasi_addr, addrlen, &addr);
if (error != __WASI_ESUCCESS) {
return error;
}

if (connect(sockfd, &addr, sizeof(addr)) < 0) {
return convert_errno(errno);
}
return __WASI_ESUCCESS;
}

static wasi_errno_t
wasi_sock_listen(wasm_exec_env_t exec_env, wasi_fd_t sockfd, int32 backlog)
{
if (listen(sockfd, backlog) < 0) {
return convert_errno(errno);
}
return __WASI_ESUCCESS;
}

static wasi_errno_t
map_buffer_to_virtaddr(const wasm_module_inst_t module_inst,
const iovec_app_t *data, uint32 data_len,
struct iovec *out)
{
uint32 i = 0;
struct iovec *iovec;
wasi_errno_t err = __WASI_ESUCCESS;

/* map buffers from the linear memory into the virtual memory address */
for (i = 0, iovec = out; i < data_len; i++, data++, iovec++) {
if (!validate_app_addr(data->buf_offset, data->buf_len)) {
err = __WASI_EINVAL;
break;
}

iovec->iov_base = addr_app_to_native(data->buf_offset);
iovec->iov_len = data->buf_len;
}

return err;
}

static wasi_errno_t
wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data,
uint32 ri_data_len, wasi_riflags_t ri_flags,
Expand All @@ -994,11 +1127,11 @@ wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data,
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
wasi_iovec_t *iovec, *iovec_begin;
struct iovec *iovec_array;
uint64 total_size;
size_t ro_datalen;
uint32 i;
ssize_t recv_size;
wasi_errno_t err;
struct msghdr hdr = { 0 };

if (!wasi_ctx)
return (wasi_errno_t)-1;
Expand All @@ -1010,34 +1143,33 @@ wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data,
|| !validate_native_addr(ri_data, (uint32)total_size))
return (wasi_errno_t)-1;

total_size = sizeof(wasi_iovec_t) * (uint64)ri_data_len;
total_size = sizeof(struct iovec) * (uint64)ri_data_len;
if (total_size >= UINT32_MAX
|| !(iovec_begin = wasm_runtime_malloc((uint32)total_size)))
|| !(iovec_array = wasm_runtime_malloc((uint32)total_size)))
return (wasi_errno_t)-1;

iovec = iovec_begin;

for (i = 0; i < ri_data_len; i++, ri_data++, iovec++) {
if (!validate_app_addr(ri_data->buf_offset, ri_data->buf_len)) {
err = (wasi_errno_t)-1;
goto fail;
}
iovec->buf = (void *)addr_app_to_native(ri_data->buf_offset);
iovec->buf_len = ri_data->buf_len;
err =
map_buffer_to_virtaddr(module_inst, ri_data, ri_data_len, iovec_array);
if (err != __WASI_ESUCCESS) {
goto fail;
}

err = wasmtime_ssp_sock_recv(curfds, sock, iovec_begin, ri_data_len,
ri_flags, &ro_datalen, ro_flags);
if (err)
goto fail;
hdr.msg_iov = iovec_array;
hdr.msg_iovlen = ri_data_len;

*(uint32 *)ro_datalen_app = (uint32)ro_datalen;
recv_size = recvmsg(sock, &hdr, ri_flags);
if (recv_size < 0) {
err = convert_errno(errno);
goto fail;
}

*(uint32 *)ro_datalen_app = (uint32)recv_size;
*ro_flags = ri_flags;
/* success */
err = 0;

fail:
wasm_runtime_free(iovec_begin);
wasm_runtime_free(iovec_array);
return err;
}

Expand All @@ -1049,11 +1181,11 @@ wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock,
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
wasi_ciovec_t *ciovec, *ciovec_begin;
struct iovec *iovec_array;
uint64 total_size;
size_t so_datalen;
uint32 i;
ssize_t send_size;
wasi_errno_t err;
struct msghdr hdr = { 0 };

if (!wasi_ctx)
return (wasi_errno_t)-1;
Expand All @@ -1064,34 +1196,32 @@ wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock,
|| !validate_native_addr((void *)si_data, (uint32)total_size))
return (wasi_errno_t)-1;

total_size = sizeof(wasi_ciovec_t) * (uint64)si_data_len;
total_size = sizeof(struct iovec) * (uint64)si_data_len;
if (total_size >= UINT32_MAX
|| !(ciovec_begin = wasm_runtime_malloc((uint32)total_size)))
|| !(iovec_array = wasm_runtime_malloc((uint32)total_size)))
return (wasi_errno_t)-1;

ciovec = ciovec_begin;

for (i = 0; i < si_data_len; i++, si_data++, ciovec++) {
if (!validate_app_addr(si_data->buf_offset, si_data->buf_len)) {
err = (wasi_errno_t)-1;
goto fail;
}
ciovec->buf = (char *)addr_app_to_native(si_data->buf_offset);
ciovec->buf_len = si_data->buf_len;
err =
map_buffer_to_virtaddr(module_inst, si_data, si_data_len, iovec_array);
if (err != __WASI_ESUCCESS) {
goto fail;
}

err = wasmtime_ssp_sock_send(curfds, sock, ciovec_begin, si_data_len,
si_flags, &so_datalen);
if (err)
goto fail;
hdr.msg_iov = iovec_array;
hdr.msg_iovlen = si_data_len;

*so_datalen_app = (uint32)so_datalen;
send_size = sendmsg(sock, &hdr, si_flags);
if (send_size < 0) {
err = convert_errno(errno);
goto fail;
}

*so_datalen_app = (uint32)send_size;
/* success */
err = 0;

fail:
wasm_runtime_free(ciovec_begin);
wasm_runtime_free(iovec_array);
return err;
}

Expand All @@ -1101,11 +1231,71 @@ wasi_sock_shutdown(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sdflags_t how)
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
int nhow;

if (!wasi_ctx)
return (wasi_errno_t)-1;

return wasmtime_ssp_sock_shutdown(curfds, sock, how);
switch (how) {
case __WASI_SHUT_RD:
nhow = SHUT_RD;
break;
case __WASI_SHUT_WR:
nhow = SHUT_WR;
break;
case __WASI_SHUT_RD | __WASI_SHUT_WR:
nhow = SHUT_RDWR;
break;
default:
return __WASI_EINVAL;
}

if (shutdown(sock, nhow) < 0) {
return convert_errno(errno);
}

return __WASI_ESUCCESS;
}

static wasi_errno_t
wasi_sock_socket(wasm_exec_env_t exec_env, int32 wasi_domain, int32 wasi_type,
int32 protocol, wasi_fd_t *ret_sockfd)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
int fd, berkeley_domain, berkeley_type;

if (!wasi_ctx)
return __WASI_EINVAL;

if (__WASI_AF_INET == wasi_domain) {
berkeley_domain = AF_INET;
}
else {
return __WASI_EAFNOSUPPORT;
}

if (__WASI_FILETYPE_SOCKET_DGRAM == wasi_type) {
berkeley_type = SOCK_DGRAM;
}
else if (__WASI_FILETYPE_SOCKET_STREAM == wasi_type) {
berkeley_type = SOCK_STREAM;
}
else {
return __WASI_ENOTSUP;
}

if (0 != protocol) {
return __WASI_EPROTONOSUPPORT;
}

fd = socket(berkeley_domain, berkeley_type, protocol);
if (fd < 0) {
return convert_errno(errno);
}

*ret_sockfd = fd;
return __WASI_ESUCCESS;
}

static wasi_errno_t
Expand Down Expand Up @@ -1161,9 +1351,14 @@ static NativeSymbol native_symbols_libc_wasi[] = {
REG_NATIVE_FUNC(proc_exit, "(i)"),
REG_NATIVE_FUNC(proc_raise, "(i)i"),
REG_NATIVE_FUNC(random_get, "(*~)i"),
REG_NATIVE_FUNC(sock_accept, "(i***)i"),
REG_NATIVE_FUNC(sock_bind, "(i*i)i"),
REG_NATIVE_FUNC(sock_connect, "(i*i)i"),
REG_NATIVE_FUNC(sock_listen, "(ii)i"),
REG_NATIVE_FUNC(sock_recv, "(i*ii**)i"),
REG_NATIVE_FUNC(sock_send, "(i*ii*)i"),
REG_NATIVE_FUNC(sock_shutdown, "(ii)i"),
REG_NATIVE_FUNC(sock_socket, "(iii*)i"),
REG_NATIVE_FUNC(sched_yield, "()i"),
};

Expand Down
3 changes: 3 additions & 0 deletions core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ typedef __wasi_roflags_t wasi_roflags_t;
typedef __wasi_siflags_t wasi_siflags_t;
typedef __wasi_sdflags_t wasi_sdflags_t;
typedef __wasi_preopentype_t wasi_preopentype_t;
typedef __wasi_socklen_t wasi_socklen_t;
typedef __wasi_sockaddr_t wasi_sockaddr_t;
typedef __wasi_sockaddr_in_t wasi_sockaddr_in_t;

#ifdef __cplusplus
}
Expand Down
Loading

0 comments on commit 862fa16

Please sign in to comment.