Implement sock_send_to and sock_recv_from system calls (#1457)

This commit is contained in:
Marcin Kolny 2022-09-13 02:00:05 +01:00 committed by GitHub
parent 56b4a8bd4c
commit b731ca4668
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 844 additions and 254 deletions

View File

@ -126,6 +126,14 @@ recvmsg(int sockfd, struct msghdr *msg, int flags);
ssize_t ssize_t
sendmsg(int sockfd, const struct msghdr *msg, int flags); sendmsg(int sockfd, const struct msghdr *msg, int flags);
ssize_t
sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
ssize_t
recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
int int
socket(int domain, int type, int protocol); socket(int domain, int type, int protocol);
@ -257,6 +265,48 @@ __wasi_sock_bind(__wasi_fd_t fd, __wasi_addr_t *addr)
(int32_t)fd, (int32_t)addr); (int32_t)fd, (int32_t)addr);
} }
/**
* Send data to a specific target
* Note: This is similar to `sendto` in POSIX
*/
int32_t
__imported_wasi_snapshot_preview1_sock_send_to(int32_t arg0, int32_t arg1,
int32_t arg2, int32_t arg3,
int32_t arg4, int32_t arg5)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_send_to")));
static inline __wasi_errno_t
__wasi_sock_send_to(__wasi_fd_t fd, const __wasi_ciovec_t *si_data,
uint32_t si_data_len, __wasi_siflags_t si_flags,
const __wasi_addr_t *dest_addr, uint32_t *so_data_len)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_send_to(
(int32_t)fd, (int32_t)si_data, (int32_t)si_data_len, (int32_t)si_flags,
(uint32_t)dest_addr, (uint32_t)so_data_len);
}
/**
* Receives data from a socket
* Note: This is similar to `recvfrom` in POSIX
*/
int32_t
__imported_wasi_snapshot_preview1_sock_recv_from(int32_t arg0, int32_t arg1,
int32_t arg2, int32_t arg3,
int32_t arg4, int32_t arg5)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_recv_from")));
static inline __wasi_errno_t
__wasi_sock_recv_from(__wasi_fd_t fd, __wasi_ciovec_t *ri_data,
uint32_t ri_data_len, __wasi_riflags_t ri_flags,
__wasi_addr_t *src_addr, uint32_t *ro_data_len)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_recv_from(
(int32_t)fd, (int32_t)ri_data, (int32_t)ri_data_len, (int32_t)ri_flags,
(uint32_t)src_addr, (uint32_t)ro_data_len);
}
/** /**
* Close a socket (this is an alias for `fd_close`) * Close a socket (this is an alias for `fd_close`)
* Note: This is similar to `close` in POSIX. * Note: This is similar to `close` in POSIX.

View File

@ -59,7 +59,7 @@ sockaddr_to_wasi_addr(const struct sockaddr *sock_addr, socklen_t addrlen,
((struct sockaddr_in *)sock_addr)->sin_port, wasi_addr); ((struct sockaddr_in *)sock_addr)->sin_port, wasi_addr);
} }
else if (AF_INET6 == sock_addr->sa_family) { else if (AF_INET6 == sock_addr->sa_family) {
assert(sizeof(struct sockaddr_in6) == addrlen); assert(sizeof(struct sockaddr_in6) <= addrlen);
ipv6_addr_to_wasi_addr( ipv6_addr_to_wasi_addr(
(uint16_t *)((struct sockaddr_in6 *)sock_addr)->sin6_addr.s6_addr, (uint16_t *)((struct sockaddr_in6 *)sock_addr)->sin6_addr.s6_addr,
((struct sockaddr_in6 *)sock_addr)->sin6_port, wasi_addr); ((struct sockaddr_in6 *)sock_addr)->sin6_port, wasi_addr);
@ -252,6 +252,66 @@ sendmsg(int sockfd, const struct msghdr *msg, int flags)
return so_datalen; return so_datalen;
} }
ssize_t
sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen)
{
// Prepare input parameters.
__wasi_ciovec_t iov = { .buf = buf, .buf_len = len };
uint32_t so_datalen = 0;
__wasi_addr_t wasi_addr;
__wasi_errno_t error;
size_t si_data_len = 1;
__wasi_siflags_t si_flags = 0;
// This implementation does not support any flags.
if (flags != 0) {
HANDLE_ERROR(__WASI_ERRNO_NOPROTOOPT)
}
error = sockaddr_to_wasi_addr(dest_addr, addrlen, &wasi_addr);
HANDLE_ERROR(error);
// Perform system call.
error = __wasi_sock_send_to(sockfd, &iov, si_data_len, si_flags, &wasi_addr,
&so_datalen);
HANDLE_ERROR(error)
return so_datalen;
}
ssize_t
recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen)
{
// Prepare input parameters.
__wasi_ciovec_t iov = { .buf = buf, .buf_len = len };
uint32_t so_datalen = 0;
__wasi_addr_t wasi_addr;
__wasi_errno_t error;
size_t si_data_len = 1;
__wasi_siflags_t si_flags = 0;
// This implementation does not support any flags.
if (flags != 0) {
HANDLE_ERROR(__WASI_ERRNO_NOPROTOOPT)
}
if (!src_addr) {
return recv(sockfd, buf, len, flags);
}
// Perform system call.
error = __wasi_sock_recv_from(sockfd, &iov, si_data_len, si_flags,
&wasi_addr, &so_datalen);
HANDLE_ERROR(error);
error = wasi_addr_to_sockaddr(&wasi_addr, src_addr, addrlen);
HANDLE_ERROR(error);
return so_datalen;
}
int int
socket(int domain, int type, int protocol) socket(int domain, int type, int protocol)
{ {

View File

@ -1274,9 +1274,70 @@ wasi_sock_set_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
} }
static wasi_errno_t static wasi_errno_t
wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data, allocate_iovec_app_buffer(wasm_module_inst_t module_inst,
uint32 ri_data_len, wasi_riflags_t ri_flags, uint32 *ro_data_len, const iovec_app_t *data, uint32 data_len,
wasi_roflags_t *ro_flags) uint8 **buf_ptr, uint64 *buf_len)
{
uint64 total_size = 0;
uint32 i;
uint8 *buf_begin = NULL;
if (data_len == 0) {
return __WASI_EINVAL;
}
total_size = sizeof(iovec_app_t) * (uint64)data_len;
if (total_size >= UINT32_MAX
|| !validate_native_addr((void *)data, (uint32)total_size))
return __WASI_EINVAL;
for (total_size = 0, i = 0; i < data_len; i++, data++) {
total_size += data->buf_len;
}
if (total_size >= UINT32_MAX
|| !(buf_begin = wasm_runtime_malloc((uint32)total_size))) {
return __WASI_ENOMEM;
}
*buf_len = total_size;
*buf_ptr = buf_begin;
return __WASI_ESUCCESS;
}
static wasi_errno_t
copy_buffer_to_iovec_app(wasm_module_inst_t module_inst, uint8 *buf_begin,
uint32 buf_size, iovec_app_t *data, uint32 data_len)
{
uint8 *buf = buf_begin;
uint32 i;
for (i = 0; i < data_len; data++, i++) {
char *native_addr;
if (!validate_app_addr(data->buf_offset, data->buf_len)) {
return __WASI_EINVAL;
}
if (buf >= buf_begin + buf_size
|| buf + data->buf_len < buf /* integer overflow */
|| buf + data->buf_len > buf_begin + buf_size) {
break;
}
native_addr = (void *)addr_app_to_native(data->buf_offset);
bh_memcpy_s(native_addr, data->buf_len, buf, data->buf_len);
buf += data->buf_len;
}
return __WASI_ESUCCESS;
}
static wasi_errno_t
wasi_sock_recv_from(wasm_exec_env_t exec_env, wasi_fd_t sock,
iovec_app_t *ri_data, uint32 ri_data_len,
wasi_riflags_t ri_flags, __wasi_addr_t *src_addr,
uint32 *ro_data_len)
{ {
/** /**
* ri_data_len is the length of a list of iovec_app_t, which head is * ri_data_len is the length of a list of iovec_app_t, which head is
@ -1286,9 +1347,6 @@ wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data,
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
uint64 total_size; uint64 total_size;
uint32 i;
iovec_app_t *ri_data_orig = ri_data;
uint8 *buf = NULL;
uint8 *buf_begin = NULL; uint8 *buf_begin = NULL;
wasi_errno_t err; wasi_errno_t err;
size_t recv_bytes = 0; size_t recv_bytes = 0;
@ -1297,55 +1355,28 @@ wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data,
return __WASI_EINVAL; return __WASI_EINVAL;
} }
if (ri_data_len == 0) { if (!validate_native_addr(ro_data_len, (uint32)sizeof(uint32)))
return __WASI_EINVAL;
}
total_size = sizeof(iovec_app_t) * (uint64)ri_data_len;
if (!validate_native_addr(ro_data_len, (uint32)sizeof(uint32))
|| !validate_native_addr(ro_flags, (uint32)sizeof(wasi_roflags_t))
|| total_size >= UINT32_MAX
|| !validate_native_addr(ri_data, (uint32)total_size))
return __WASI_EINVAL; return __WASI_EINVAL;
/* receive and scatter*/ err = allocate_iovec_app_buffer(module_inst, ri_data, ri_data_len,
for (total_size = 0, i = 0; i < ri_data_len; i++, ri_data++) { &buf_begin, &total_size);
total_size += ri_data->buf_len; if (err != __WASI_ESUCCESS) {
} goto fail;
if (total_size >= UINT32_MAX
|| !(buf_begin = wasm_runtime_malloc((uint32)total_size))) {
return __WASI_ENOMEM;
} }
memset(buf_begin, 0, total_size); memset(buf_begin, 0, total_size);
*ro_data_len = 0; *ro_data_len = 0;
err = wasmtime_ssp_sock_recv(curfds, sock, buf_begin, total_size, err = wasmtime_ssp_sock_recv_from(curfds, sock, buf_begin, total_size,
&recv_bytes); ri_flags, src_addr, &recv_bytes);
if (err != __WASI_ESUCCESS) { if (err != __WASI_ESUCCESS) {
goto fail; goto fail;
} }
*ro_data_len = (uint32)recv_bytes; *ro_data_len = (uint32)recv_bytes;
buf = buf_begin; err = copy_buffer_to_iovec_app(module_inst, buf_begin, (uint32)recv_bytes,
ri_data = ri_data_orig; ri_data, ri_data_len);
for (i = 0; i < ri_data_len; ri_data++, i++) {
char *native_addr;
if ((uint32)(buf - buf_begin) >= *ro_data_len) {
break;
}
if (!validate_app_addr(ri_data->buf_offset, ri_data->buf_len)) {
err = __WASI_EINVAL;
goto fail;
}
native_addr = (void *)addr_app_to_native(ri_data->buf_offset);
bh_memcpy_s(native_addr, ri_data->buf_len, buf, ri_data->buf_len);
buf += ri_data->buf_len;
}
*ro_flags = ri_flags;
fail: fail:
if (buf_begin) { if (buf_begin) {
wasm_runtime_free(buf_begin); wasm_runtime_free(buf_begin);
@ -1353,6 +1384,59 @@ fail:
return err; 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, uint32 *ro_data_len,
wasi_roflags_t *ro_flags)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
__wasi_addr_t src_addr;
wasi_errno_t error;
if (!validate_native_addr(ro_flags, (uint32)sizeof(wasi_roflags_t)))
return __WASI_EINVAL;
error = wasi_sock_recv_from(exec_env, sock, ri_data, ri_data_len, ri_flags,
&src_addr, ro_data_len);
*ro_flags = ri_flags;
return error;
}
static wasi_errno_t
convert_iovec_app_to_buffer(wasm_module_inst_t module_inst,
const iovec_app_t *si_data, uint32 si_data_len,
uint8 **buf_ptr, uint64 *buf_len)
{
uint32 i;
const iovec_app_t *si_data_orig = si_data;
uint8 *buf = NULL;
wasi_errno_t error;
error = allocate_iovec_app_buffer(module_inst, si_data, si_data_len,
buf_ptr, buf_len);
if (error != __WASI_ESUCCESS) {
return error;
}
buf = *buf_ptr;
si_data = si_data_orig;
for (i = 0; i < si_data_len; i++, si_data++) {
char *native_addr;
if (!validate_app_addr(si_data->buf_offset, si_data->buf_len)) {
wasm_runtime_free(*buf_ptr);
return __WASI_EINVAL;
}
native_addr = (char *)addr_app_to_native(si_data->buf_offset);
bh_memcpy_s(buf, si_data->buf_len, native_addr, si_data->buf_len);
buf += si_data->buf_len;
}
return __WASI_ESUCCESS;
}
static wasi_errno_t static wasi_errno_t
wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock,
const iovec_app_t *si_data, uint32 si_data_len, const iovec_app_t *si_data, uint32 si_data_len,
@ -1365,11 +1449,8 @@ wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock,
wasm_module_inst_t module_inst = get_module_inst(exec_env); wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
uint64 total_size = 0; uint64 buf_size = 0;
uint32 i;
const iovec_app_t *si_data_orig = si_data;
uint8 *buf = NULL; uint8 *buf = NULL;
uint8 *buf_begin = NULL;
wasi_errno_t err; wasi_errno_t err;
size_t send_bytes = 0; size_t send_bytes = 0;
@ -1377,49 +1458,61 @@ wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock,
return __WASI_EINVAL; return __WASI_EINVAL;
} }
if (si_data_len == 0) { if (!validate_native_addr(so_data_len, sizeof(uint32)))
return __WASI_EINVAL;
}
total_size = sizeof(iovec_app_t) * (uint64)si_data_len;
if (!validate_native_addr(so_data_len, sizeof(uint32))
|| total_size >= UINT32_MAX
|| !validate_native_addr((void *)si_data, (uint32)total_size))
return __WASI_EINVAL; return __WASI_EINVAL;
/* gather and send */ err = convert_iovec_app_to_buffer(module_inst, si_data, si_data_len, &buf,
for (total_size = 0, i = 0; i < si_data_len; i++, si_data++) { &buf_size);
total_size += si_data->buf_len; if (err != __WASI_ESUCCESS)
} return err;
if (total_size >= UINT32_MAX
|| !(buf_begin = wasm_runtime_malloc((uint32)total_size))) {
return __WASI_ENOMEM;
}
buf = buf_begin;
si_data = si_data_orig;
for (i = 0; i < si_data_len; i++, si_data++) {
char *native_addr;
if (!validate_app_addr(si_data->buf_offset, si_data->buf_len)) {
err = __WASI_EINVAL;
goto fail;
}
native_addr = (char *)addr_app_to_native(si_data->buf_offset);
bh_memcpy_s(buf, si_data->buf_len, native_addr, si_data->buf_len);
buf += si_data->buf_len;
}
*so_data_len = 0; *so_data_len = 0;
err = wasmtime_ssp_sock_send(curfds, sock, buf_begin, total_size, err = wasmtime_ssp_sock_send(curfds, sock, buf, buf_size, &send_bytes);
&send_bytes);
*so_data_len = (uint32)send_bytes; *so_data_len = (uint32)send_bytes;
fail: wasm_runtime_free(buf);
if (buf_begin) {
wasm_runtime_free(buf_begin); return err;
}
static wasi_errno_t
wasi_sock_send_to(wasm_exec_env_t exec_env, wasi_fd_t sock,
const iovec_app_t *si_data, uint32 si_data_len,
wasi_siflags_t si_flags, const __wasi_addr_t *dest_addr,
uint32 *so_data_len)
{
/**
* si_data_len is the length of a list of iovec_app_t, which head is
* si_data. so_data_len is the number of bytes sent
**/
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);
uint64 buf_size = 0;
uint8 *buf = NULL;
wasi_errno_t err;
size_t send_bytes = 0;
struct addr_pool *addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx);
if (!wasi_ctx) {
return __WASI_EINVAL;
} }
if (!validate_native_addr(so_data_len, sizeof(uint32)))
return __WASI_EINVAL;
err = convert_iovec_app_to_buffer(module_inst, si_data, si_data_len, &buf,
&buf_size);
if (err != __WASI_ESUCCESS)
return err;
*so_data_len = 0;
err = wasmtime_ssp_sock_send_to(curfds, addr_pool, sock, buf, buf_size,
si_flags, dest_addr, &send_bytes);
*so_data_len = (uint32)send_bytes;
wasm_runtime_free(buf);
return err; return err;
} }
@ -1505,7 +1598,9 @@ static NativeSymbol native_symbols_libc_wasi[] = {
REG_NATIVE_FUNC(sock_listen, "(ii)i"), REG_NATIVE_FUNC(sock_listen, "(ii)i"),
REG_NATIVE_FUNC(sock_open, "(iii*)i"), REG_NATIVE_FUNC(sock_open, "(iii*)i"),
REG_NATIVE_FUNC(sock_recv, "(i*ii**)i"), REG_NATIVE_FUNC(sock_recv, "(i*ii**)i"),
REG_NATIVE_FUNC(sock_recv_from, "(i*ii**)i"),
REG_NATIVE_FUNC(sock_send, "(i*ii*)i"), REG_NATIVE_FUNC(sock_send, "(i*ii*)i"),
REG_NATIVE_FUNC(sock_send_to, "(i*ii**)i"),
REG_NATIVE_FUNC(sock_set_recv_buf_size, "(ii)i"), REG_NATIVE_FUNC(sock_set_recv_buf_size, "(ii)i"),
REG_NATIVE_FUNC(sock_set_recv_timeout, "(iI)i"), REG_NATIVE_FUNC(sock_set_recv_timeout, "(iI)i"),
REG_NATIVE_FUNC(sock_set_reuse_addr, "(ii)i"), REG_NATIVE_FUNC(sock_set_reuse_addr, "(ii)i"),

View File

@ -1071,6 +1071,18 @@ __wasi_errno_t wasmtime_ssp_sock_recv(
size_t *recv_len size_t *recv_len
) WASMTIME_SSP_SYSCALL_NAME(sock_recv) __attribute__((__warn_unused_result__)); ) WASMTIME_SSP_SYSCALL_NAME(sock_recv) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_recv_from(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
void *buf,
size_t buf_len,
__wasi_riflags_t ri_flags,
__wasi_addr_t *src_addr,
size_t *recv_len
) WASMTIME_SSP_SYSCALL_NAME(sock_recv_from) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_send( __wasi_errno_t wasmtime_ssp_sock_send(
#if !defined(WASMTIME_SSP_STATIC_CURFDS) #if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, struct fd_table *curfds,
@ -1081,6 +1093,18 @@ __wasi_errno_t wasmtime_ssp_sock_send(
size_t *sent_len size_t *sent_len
) WASMTIME_SSP_SYSCALL_NAME(sock_send) __attribute__((__warn_unused_result__)); ) WASMTIME_SSP_SYSCALL_NAME(sock_send) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_send_to(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, struct addr_pool *addr_pool,
#endif
__wasi_fd_t sock,
const void *buf,
size_t buf_len,
__wasi_siflags_t si_flags,
const __wasi_addr_t *dest_addr,
size_t *sent_len
) WASMTIME_SSP_SYSCALL_NAME(sock_send_to) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_shutdown( __wasi_errno_t wasmtime_ssp_sock_shutdown(
#if !defined(WASMTIME_SSP_STATIC_CURFDS) #if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, struct fd_table *curfds,

View File

@ -224,35 +224,59 @@ convert_clockid(__wasi_clockid_t in, clockid_t *out)
} }
} }
// Converts an IPv4 binary address object to WASI address.
static void static void
ipv4_addr_to_wasi_addr(uint32_t addr, __wasi_ip_port_t port, __wasi_addr_t *out) wasi_addr_to_bh_sockaddr(const __wasi_addr_t *wasi_addr,
bh_sockaddr_t *sockaddr)
{ {
addr = ntohl(addr); if (wasi_addr->kind == IPv4) {
sockaddr->addr_bufer.ipv4 = (wasi_addr->addr.ip4.addr.n0 << 24)
out->kind = IPv4; | (wasi_addr->addr.ip4.addr.n1 << 16)
out->addr.ip4.port = port; | (wasi_addr->addr.ip4.addr.n2 << 8)
out->addr.ip4.addr.n0 = (addr & 0xFF000000) >> 24; | wasi_addr->addr.ip4.addr.n3;
out->addr.ip4.addr.n1 = (addr & 0x00FF0000) >> 16; sockaddr->is_ipv4 = true;
out->addr.ip4.addr.n2 = (addr & 0x0000FF00) >> 8; sockaddr->port = wasi_addr->addr.ip4.port;
out->addr.ip4.addr.n3 = (addr & 0x000000FF); }
else {
sockaddr->addr_bufer.ipv6[0] = wasi_addr->addr.ip6.addr.n0;
sockaddr->addr_bufer.ipv6[1] = wasi_addr->addr.ip6.addr.n1;
sockaddr->addr_bufer.ipv6[2] = wasi_addr->addr.ip6.addr.n2;
sockaddr->addr_bufer.ipv6[3] = wasi_addr->addr.ip6.addr.n3;
sockaddr->addr_bufer.ipv6[4] = wasi_addr->addr.ip6.addr.h0;
sockaddr->addr_bufer.ipv6[5] = wasi_addr->addr.ip6.addr.h1;
sockaddr->addr_bufer.ipv6[6] = wasi_addr->addr.ip6.addr.h2;
sockaddr->addr_bufer.ipv6[7] = wasi_addr->addr.ip6.addr.h3;
sockaddr->is_ipv4 = false;
sockaddr->port = wasi_addr->addr.ip6.port;
}
} }
// Converts an IPv6 binary address object to WASI address object.
static void static void
ipv6_addr_to_wasi_addr(uint16_t addr[8], __wasi_ip_port_t port, bh_sockaddr_to_wasi_addr(const bh_sockaddr_t *sockaddr,
__wasi_addr_t *out) __wasi_addr_t *wasi_addr)
{ {
out->kind = IPv6; if (sockaddr->is_ipv4) {
out->addr.ip6.port = port; wasi_addr->kind = IPv4;
out->addr.ip6.addr.n0 = addr[0]; wasi_addr->addr.ip4.port = sockaddr->port;
out->addr.ip6.addr.n1 = addr[1]; wasi_addr->addr.ip4.addr.n0 =
out->addr.ip6.addr.n2 = addr[2]; (sockaddr->addr_bufer.ipv4 & 0xFF000000) >> 24;
out->addr.ip6.addr.n3 = addr[3]; wasi_addr->addr.ip4.addr.n1 =
out->addr.ip6.addr.h0 = addr[4]; (sockaddr->addr_bufer.ipv4 & 0x00FF0000) >> 16;
out->addr.ip6.addr.h1 = addr[5]; wasi_addr->addr.ip4.addr.n2 =
out->addr.ip6.addr.h2 = addr[6]; (sockaddr->addr_bufer.ipv4 & 0x0000FF00) >> 8;
out->addr.ip6.addr.h3 = addr[7]; wasi_addr->addr.ip4.addr.n3 = (sockaddr->addr_bufer.ipv4 & 0x000000FF);
}
else {
wasi_addr->kind = IPv6;
wasi_addr->addr.ip6.port = sockaddr->port;
wasi_addr->addr.ip6.addr.n0 = sockaddr->addr_bufer.ipv6[0];
wasi_addr->addr.ip6.addr.n1 = sockaddr->addr_bufer.ipv6[1];
wasi_addr->addr.ip6.addr.n2 = sockaddr->addr_bufer.ipv6[2];
wasi_addr->addr.ip6.addr.n3 = sockaddr->addr_bufer.ipv6[3];
wasi_addr->addr.ip6.addr.h0 = sockaddr->addr_bufer.ipv6[4];
wasi_addr->addr.ip6.addr.h1 = sockaddr->addr_bufer.ipv6[5];
wasi_addr->addr.ip6.addr.h2 = sockaddr->addr_bufer.ipv6[6];
wasi_addr->addr.ip6.addr.h3 = sockaddr->addr_bufer.ipv6[7];
}
} }
__wasi_errno_t __wasi_errno_t
@ -2911,9 +2935,7 @@ wasi_ssp_sock_addr_local(
__wasi_fd_t fd, __wasi_addr_t *addr) __wasi_fd_t fd, __wasi_addr_t *addr)
{ {
struct fd_object *fo; struct fd_object *fo;
uint8 buf[16]; bh_sockaddr_t bh_addr;
__wasi_ip_port_t port;
uint8 is_ipv4;
int ret; int ret;
__wasi_errno_t error = __wasi_errno_t error =
@ -2921,19 +2943,13 @@ wasi_ssp_sock_addr_local(
if (error != __WASI_ESUCCESS) if (error != __WASI_ESUCCESS)
return error; return error;
ret = os_socket_addr_local(fd_number(fo), buf, sizeof(buf) / sizeof(buf[0]), ret = os_socket_addr_local(fd_number(fo), &bh_addr);
&port, &is_ipv4);
fd_object_release(fo); fd_object_release(fo);
if (ret != BHT_OK) { if (ret != BHT_OK) {
return convert_errno(errno); return convert_errno(errno);
} }
if (is_ipv4) { bh_sockaddr_to_wasi_addr(&bh_addr, addr);
ipv4_addr_to_wasi_addr(*(uint32_t *)buf, port, addr);
}
else {
ipv6_addr_to_wasi_addr((uint16 *)buf, port, addr);
}
return __WASI_ESUCCESS; return __WASI_ESUCCESS;
} }
@ -2946,9 +2962,7 @@ wasi_ssp_sock_addr_remote(
__wasi_fd_t fd, __wasi_addr_t *addr) __wasi_fd_t fd, __wasi_addr_t *addr)
{ {
struct fd_object *fo; struct fd_object *fo;
uint8 buf[16]; bh_sockaddr_t bh_addr;
__wasi_ip_port_t port;
uint8 is_ipv4;
int ret; int ret;
__wasi_errno_t error = __wasi_errno_t error =
@ -2956,25 +2970,19 @@ wasi_ssp_sock_addr_remote(
if (error != __WASI_ESUCCESS) if (error != __WASI_ESUCCESS)
return error; return error;
ret = os_socket_addr_remote(fd_number(fo), buf, ret = os_socket_addr_remote(fd_number(fo), &bh_addr);
sizeof(buf) / sizeof(buf[0]), &port, &is_ipv4);
fd_object_release(fo); fd_object_release(fo);
if (ret != BHT_OK) { if (ret != BHT_OK) {
return convert_errno(errno); return convert_errno(errno);
} }
if (is_ipv4) { bh_sockaddr_to_wasi_addr(&bh_addr, addr);
ipv4_addr_to_wasi_addr(*(uint32_t *)buf, port, addr);
}
else {
ipv6_addr_to_wasi_addr((uint16 *)buf, port, addr);
}
return __WASI_ESUCCESS; return __WASI_ESUCCESS;
} }
static bool static bool
wasi_addr_to_string(__wasi_addr_t *addr, char *buf, size_t buflen) wasi_addr_to_string(const __wasi_addr_t *addr, char *buf, size_t buflen)
{ {
if (addr->kind == IPv4) { if (addr->kind == IPv4) {
const char *format = "%u.%u.%u.%u"; const char *format = "%u.%u.%u.%u";
@ -3077,14 +3085,8 @@ wasi_ssp_sock_addr_resolve(
for (size_t i = 0; i < actual_info_size; i++) { for (size_t i = 0; i < actual_info_size; i++) {
addr_info[i].type = addr_info[i].type =
wamr_addr_info[i].is_tcp ? SOCKET_STREAM : SOCKET_DGRAM; wamr_addr_info[i].is_tcp ? SOCKET_STREAM : SOCKET_DGRAM;
if (wamr_addr_info[i].is_ipv4) { bh_sockaddr_to_wasi_addr(&wamr_addr_info[i].sockaddr,
ipv4_addr_to_wasi_addr(*(uint32_t *)wamr_addr_info[i].addr, &addr_info[i].addr);
wamr_addr_info[i].port, &addr_info[i].addr);
}
else {
ipv6_addr_to_wasi_addr((uint16_t *)wamr_addr_info[i].addr,
wamr_addr_info[i].port, &addr_info[i].addr);
}
} }
wasm_runtime_free(wamr_addr_info); wasm_runtime_free(wamr_addr_info);
@ -3202,9 +3204,24 @@ wasmtime_ssp_sock_recv(
struct fd_table *curfds, struct fd_table *curfds,
#endif #endif
__wasi_fd_t sock, void *buf, size_t buf_len, size_t *recv_len) __wasi_fd_t sock, void *buf, size_t buf_len, size_t *recv_len)
{
__wasi_addr_t src_addr;
return wasmtime_ssp_sock_recv_from(curfds, sock, buf, buf_len, 0, &src_addr,
recv_len);
}
__wasi_errno_t
wasmtime_ssp_sock_recv_from(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock, void *buf, size_t buf_len, __wasi_riflags_t ri_flags,
__wasi_addr_t *src_addr, size_t *recv_len)
{ {
struct fd_object *fo; struct fd_object *fo;
__wasi_errno_t error; __wasi_errno_t error;
bh_sockaddr_t sockaddr;
int ret; int ret;
error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_READ, 0); error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_READ, 0);
@ -3212,12 +3229,14 @@ wasmtime_ssp_sock_recv(
return error; return error;
} }
ret = os_socket_recv(fd_number(fo), buf, buf_len); ret = os_socket_recv_from(fd_number(fo), buf, buf_len, 0, &sockaddr);
fd_object_release(fo); fd_object_release(fo);
if (-1 == ret) { if (-1 == ret) {
return convert_errno(errno); return convert_errno(errno);
} }
bh_sockaddr_to_wasi_addr(&sockaddr, src_addr);
*recv_len = (size_t)ret; *recv_len = (size_t)ret;
return __WASI_ESUCCESS; return __WASI_ESUCCESS;
} }
@ -3248,6 +3267,45 @@ wasmtime_ssp_sock_send(
return __WASI_ESUCCESS; return __WASI_ESUCCESS;
} }
__wasi_errno_t
wasmtime_ssp_sock_send_to(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, struct addr_pool *addr_pool,
#endif
__wasi_fd_t sock, const void *buf, size_t buf_len,
__wasi_siflags_t si_flags, const __wasi_addr_t *dest_addr, size_t *sent_len)
{
char addr_buf[48] = { 0 };
struct fd_object *fo;
__wasi_errno_t error;
int ret;
bh_sockaddr_t sockaddr;
if (!wasi_addr_to_string(dest_addr, addr_buf, sizeof(addr_buf))) {
return __WASI_EPROTONOSUPPORT;
}
if (!addr_pool_search(addr_pool, addr_buf)) {
return __WASI_EACCES;
}
error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_WRITE, 0);
if (error != 0) {
return error;
}
wasi_addr_to_bh_sockaddr(dest_addr, &sockaddr);
ret = os_socket_send_to(fd_number(fo), buf, buf_len, 0, &sockaddr);
fd_object_release(fo);
if (-1 == ret) {
return convert_errno(errno);
}
*sent_len = (size_t)ret;
return __WASI_ESUCCESS;
}
__wasi_errno_t __wasi_errno_t
wasmtime_ssp_sock_shutdown( wasmtime_ssp_sock_shutdown(
#if !defined(WASMTIME_SSP_STATIC_CURFDS) #if !defined(WASMTIME_SSP_STATIC_CURFDS)
@ -3403,7 +3461,7 @@ addr_pool_insert(struct addr_pool *addr_pool, const char *addr, uint8 mask)
{ {
struct addr_pool *cur = addr_pool; struct addr_pool *cur = addr_pool;
struct addr_pool *next; struct addr_pool *next;
bh_inet_network_output_t target; bh_ip_addr_buffer_t target;
if (!addr_pool) { if (!addr_pool) {
return false; return false;
@ -3464,7 +3522,7 @@ init_address_mask(uint8_t *buf, size_t buflen, size_t mask)
/* target must be in network byte order */ /* target must be in network byte order */
static bool static bool
compare_address(const struct addr_pool *addr_pool_entry, compare_address(const struct addr_pool *addr_pool_entry,
bh_inet_network_output_t *target) bh_ip_addr_buffer_t *target)
{ {
uint8_t maskbuf[16] = { 0 }; uint8_t maskbuf[16] = { 0 };
uint8_t basebuf[16] = { 0 }; uint8_t basebuf[16] = { 0 };
@ -3515,7 +3573,7 @@ bool
addr_pool_search(struct addr_pool *addr_pool, const char *addr) addr_pool_search(struct addr_pool *addr_pool, const char *addr)
{ {
struct addr_pool *cur = addr_pool->next; struct addr_pool *cur = addr_pool->next;
bh_inet_network_output_t target; bh_ip_addr_buffer_t target;
__wasi_addr_type_t addr_type; __wasi_addr_type_t addr_type;
if (os_socket_inet_network(true, addr, &target) != BHT_OK) { if (os_socket_inet_network(true, addr, &target) != BHT_OK) {

View File

@ -34,6 +34,77 @@ textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr *out)
return false; return false;
} }
static int
sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr, socklen_t socklen,
bh_sockaddr_t *bh_sockaddr)
{
switch (sockaddr->sa_family) {
case AF_INET:
{
struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
assert(socklen >= sizeof(struct sockaddr_in));
bh_sockaddr->port = ntohs(addr->sin_port);
bh_sockaddr->addr_bufer.ipv4 = ntohl(addr->sin_addr.s_addr);
bh_sockaddr->is_ipv4 = true;
return BHT_OK;
}
case AF_INET6:
{
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)sockaddr;
size_t i;
assert(socklen >= sizeof(struct sockaddr_in6));
bh_sockaddr->port = ntohs(addr->sin6_port);
for (i = 0; i < sizeof(bh_sockaddr->addr_bufer.ipv6)
/ sizeof(bh_sockaddr->addr_bufer.ipv6[0]);
i++) {
uint16 part_addr = addr->sin6_addr.s6_addr[i * 2]
| (addr->sin6_addr.s6_addr[i * 2 + 1] << 8);
bh_sockaddr->addr_bufer.ipv6[i] = ntohs(part_addr);
}
bh_sockaddr->is_ipv4 = false;
return BHT_OK;
}
default:
errno = EAFNOSUPPORT;
return BHT_ERROR;
}
}
static void
bh_sockaddr_to_sockaddr(const bh_sockaddr_t *bh_sockaddr,
struct sockaddr_storage *sockaddr, socklen_t *socklen)
{
if (bh_sockaddr->is_ipv4) {
struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
addr->sin_port = htons(bh_sockaddr->port);
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_bufer.ipv4);
*socklen = sizeof(*addr);
}
else {
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)sockaddr;
size_t i;
addr->sin6_port = htons(bh_sockaddr->port);
addr->sin6_family = AF_INET6;
for (i = 0; i < sizeof(bh_sockaddr->addr_bufer.ipv6)
/ sizeof(bh_sockaddr->addr_bufer.ipv6[0]);
i++) {
uint16 part_addr = htons(bh_sockaddr->addr_bufer.ipv6[i]);
addr->sin6_addr.s6_addr[i * 2] = 0xff & part_addr;
addr->sin6_addr.s6_addr[i * 2 + 1] = (0xff00 & part_addr) >> 8;
}
*socklen = sizeof(*addr);
}
}
int int
os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp) os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp)
{ {
@ -168,12 +239,48 @@ os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
return recv(socket, buf, len, 0); return recv(socket, buf, len, 0);
} }
int
os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
bh_sockaddr_t *src_addr)
{
struct sockaddr_storage sock_addr = {};
socklen_t socklen = sizeof(sock_addr);
int ret;
ret = recvfrom(socket, buf, len, flags, (struct sockaddr *)&sock_addr,
&socklen);
if (ret < 0) {
return ret;
}
if (src_addr) {
sockaddr_to_bh_sockaddr((struct sockaddr *)&sock_addr, socklen,
src_addr);
}
return ret;
}
int int
os_socket_send(bh_socket_t socket, const void *buf, unsigned int len) os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
{ {
return send(socket, buf, len, 0); return send(socket, buf, len, 0);
} }
int
os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
int flags, const bh_sockaddr_t *dest_addr)
{
struct sockaddr_storage sock_addr = {};
socklen_t socklen = 0;
bh_sockaddr_to_sockaddr(dest_addr, &sock_addr, &socklen);
return sendto(socket, buf, len, 0, (const struct sockaddr *)&sock_addr,
socklen);
}
int int
os_socket_close(bh_socket_t socket) os_socket_close(bh_socket_t socket)
{ {
@ -189,8 +296,7 @@ os_socket_shutdown(bh_socket_t socket)
} }
int int
os_socket_inet_network(bool is_ipv4, const char *cp, os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out)
bh_inet_network_output_t *out)
{ {
if (!cp) if (!cp)
return BHT_ERROR; return BHT_ERROR;
@ -278,26 +384,8 @@ os_socket_addr_resolve(const char *host, const char *service,
continue; continue;
} }
if (res->ai_family == AF_INET) { sockaddr_to_bh_sockaddr(res->ai_addr, sizeof(struct sockaddr_in),
struct sockaddr_in *addr_in = &addr_info[pos].sockaddr);
(struct sockaddr_in *)res->ai_addr;
addr_info[pos].port = addr_in->sin_port;
addr_info[pos].is_ipv4 = 1;
memcpy(addr_info[pos].addr, &addr_in->sin_addr,
sizeof(addr_in->sin_addr));
}
else {
struct sockaddr_in6 *addr_in =
(struct sockaddr_in6 *)res->ai_addr;
addr_info[pos].port = addr_in->sin6_port;
addr_info[pos].is_ipv4 = 0;
for (int i = 0; i < 8; i++) {
((uint16 *)addr_info[pos].addr)[i] =
ntohs(((uint16_t *)&addr_in->sin6_addr)[i]);
}
}
addr_info[pos].is_tcp = res->ai_socktype == SOCK_STREAM; addr_info[pos].is_tcp = res->ai_socktype == SOCK_STREAM;
} }
@ -312,45 +400,6 @@ os_socket_addr_resolve(const char *host, const char *service,
return BHT_OK; return BHT_OK;
} }
static int
os_socket_convert_sockaddr(struct sockaddr *addr, uint8_t *buf, size_t buflen,
uint16_t *port, uint8_t *is_ipv4)
{
assert(buf);
assert(is_ipv4);
assert(port);
switch (addr->sa_family) {
case AF_INET:
{
struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
assert(buflen >= sizeof(addr_in->sin_addr));
*port = ntohs(addr_in->sin_port);
memcpy(buf, &addr_in->sin_addr, sizeof(addr_in->sin_addr));
*is_ipv4 = true;
break;
}
case AF_INET6:
{
struct sockaddr_in6 *addr_in = (struct sockaddr_in6 *)addr;
assert(buflen >= sizeof(addr_in->sin6_addr));
*port = ntohs(addr_in->sin6_port);
for (int i = 0; i < 8; i++) {
((uint16_t *)buf)[i] =
ntohs(((uint16_t *)&addr_in->sin6_addr)[i]);
}
*is_ipv4 = false;
break;
}
default:
return BHT_ERROR;
}
return BHT_OK;
}
int int
os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us) os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us)
{ {
@ -400,8 +449,7 @@ os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us)
} }
int int
os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen, os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
uint16_t *port, uint8_t *is_ipv4)
{ {
struct sockaddr_storage addr_storage = { 0 }; struct sockaddr_storage addr_storage = { 0 };
socklen_t addr_len = sizeof(addr_storage); socklen_t addr_len = sizeof(addr_storage);
@ -413,13 +461,12 @@ os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
return BHT_ERROR; return BHT_ERROR;
} }
return os_socket_convert_sockaddr((struct sockaddr *)&addr_storage, buf, return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr_storage, addr_len,
buflen, port, is_ipv4); sockaddr);
} }
int int
os_socket_addr_remote(bh_socket_t socket, uint8_t *buf, size_t buflen, os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr)
uint16_t *port, uint8_t *is_ipv4)
{ {
struct sockaddr_storage addr_storage = { 0 }; struct sockaddr_storage addr_storage = { 0 };
socklen_t addr_len = sizeof(addr_storage); socklen_t addr_len = sizeof(addr_storage);
@ -431,6 +478,6 @@ os_socket_addr_remote(bh_socket_t socket, uint8_t *buf, size_t buflen,
return BHT_ERROR; return BHT_ERROR;
} }
return os_socket_convert_sockaddr((struct sockaddr *)&addr_storage, buf, return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr_storage, addr_len,
buflen, port, is_ipv4); sockaddr);
} }

View File

@ -292,6 +292,18 @@ os_sem_unlink(const char *name);
* need to implement these APIs * need to implement these APIs
*/ */
typedef union {
uint32 ipv4;
uint16 ipv6[8];
uint8 data[1];
} bh_ip_addr_buffer_t;
typedef struct {
bh_ip_addr_buffer_t addr_bufer;
uint16 port;
bool is_ipv4;
} bh_sockaddr_t;
/** /**
* Create a socket * Create a socket
* *
@ -381,6 +393,22 @@ os_socket_connect(bh_socket_t socket, const char *addr, int port);
int int
os_socket_recv(bh_socket_t socket, void *buf, unsigned int len); os_socket_recv(bh_socket_t socket, void *buf, unsigned int len);
/**
* Blocking receive message from a socket.
*
* @param socket the socket to send message
* @param buf the buffer to store the data
* @param len length of the buffer, this API does not guarantee that
* [len] bytes are received
* @param flags control the operation
* @param src_addr source address
*
* @return number of bytes sent if success, -1 otherwise
*/
int
os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
bh_sockaddr_t *src_addr);
/** /**
* Blocking send message on a socket * Blocking send message on a socket
* *
@ -393,6 +421,21 @@ os_socket_recv(bh_socket_t socket, void *buf, unsigned int len);
int int
os_socket_send(bh_socket_t socket, const void *buf, unsigned int len); os_socket_send(bh_socket_t socket, const void *buf, unsigned int len);
/**
* Blocking send message on a socket to the target address
*
* @param socket the socket to send message
* @param buf the buffer of data to be sent
* @param len length of the buffer
* @param flags control the operation
* @param dest_addr target address
*
* @return number of bytes sent if success, -1 otherwise
*/
int
os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
int flags, const bh_sockaddr_t *dest_addr);
/** /**
* Close a socket * Close a socket
* *
@ -413,12 +456,6 @@ os_socket_close(bh_socket_t socket);
int int
os_socket_shutdown(bh_socket_t socket); os_socket_shutdown(bh_socket_t socket);
typedef union {
uint32 ipv4;
uint16 ipv6[8];
uint8_t data[0];
} bh_inet_network_output_t;
/** /**
* converts cp into a number in host byte order suitable for use as * converts cp into a number in host byte order suitable for use as
* an Internet network address * an Internet network address
@ -435,13 +472,10 @@ typedef union {
* If the input is invalid, -1 is returned * If the input is invalid, -1 is returned
*/ */
int int
os_socket_inet_network(bool is_ipv4, const char *cp, os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out);
bh_inet_network_output_t *out);
typedef struct { typedef struct {
uint8_t addr[16]; bh_sockaddr_t sockaddr;
uint16_t port;
uint8_t is_ipv4;
uint8_t is_tcp; uint8_t is_tcp;
} bh_addr_info_t; } bh_addr_info_t;
@ -478,38 +512,24 @@ os_socket_addr_resolve(const char *host, const char *service,
* *
* @param socket the local socket * @param socket the local socket
* *
* @param buf buffer to store the address * @param sockaddr a buffer for storing the address
*
* @param buflen length of the buf buffer
*
* @param port a buffer for storing socket's port
*
* @param is_ipv4 a buffer for storing information about the address family
* *
* @return On success, returns 0; otherwise, it returns -1. * @return On success, returns 0; otherwise, it returns -1.
*/ */
int int
os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen, os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr);
uint16_t *port, uint8_t *is_ipv4);
/** /**
* Returns an binary address and a port of the remote socket * Returns an binary address and a port of the remote socket
* *
* @param socket the remote socket * @param socket the remote socket
* *
* @param buf buffer to store the address * @param sockaddr a buffer for storing the address
*
* @param buflen length of the buf buffer
*
* @param port a buffer for storing socket's port
*
* @param is_ipv4 a buffer for storing information about the address family
* *
* @return On success, returns 0; otherwise, it returns -1. * @return On success, returns 0; otherwise, it returns -1.
*/ */
int int
os_socket_addr_remote(bh_socket_t socket, uint8_t *buf, size_t buflen, os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr);
uint16_t *port, uint8_t *is_ipv4);
/** /**
* Set the send timeout until reporting an error * Set the send timeout until reporting an error

View File

@ -605,8 +605,7 @@ os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp)
} }
int int
os_socket_inet_network(bool is_ipv4, const char *cp, os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out)
bh_inet_network_output_t *out)
{ {
if (!cp) if (!cp)
return BHT_ERROR; return BHT_ERROR;
@ -662,6 +661,15 @@ os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
return ret; return ret;
} }
int
os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
bh_sockaddr_t *src_addr)
{
errno = ENOSYS;
return BHT_ERROR;
}
int int
os_socket_send(bh_socket_t socket, const void *buf, unsigned int len) os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
{ {
@ -678,6 +686,15 @@ os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
return ret; return ret;
} }
int
os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
int flags, const bh_sockaddr_t *dest_addr)
{
errno = ENOSYS;
return BHT_ERROR;
}
int int
os_socket_shutdown(bh_socket_t socket) os_socket_shutdown(bh_socket_t socket)
{ {
@ -696,8 +713,7 @@ os_socket_addr_resolve(const char *host, const char *service,
} }
int int
os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen, os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
uint16_t *port, uint8_t *is_ipv4)
{ {
errno = ENOSYS; errno = ENOSYS;
@ -705,8 +721,7 @@ os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
} }
int int
os_socket_addr_remote(bh_socket_t socket, uint8_t *buf, size_t buflen, os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr)
uint16_t *port, uint8_t *is_ipv4)
{ {
errno = ENOSYS; errno = ENOSYS;

View File

@ -143,12 +143,30 @@ os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
return recv(socket, buf, len, 0); return recv(socket, buf, len, 0);
} }
int
os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
bh_sockaddr_t *src_addr)
{
errno = ENOSYS;
return BHT_ERROR;
}
int int
os_socket_send(bh_socket_t socket, const void *buf, unsigned int len) os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
{ {
return send(socket, buf, len, 0); return send(socket, buf, len, 0);
} }
int
os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
int flags, const bh_sockaddr_t *dest_addr)
{
errno = ENOSYS;
return BHT_ERROR;
}
int int
os_socket_close(bh_socket_t socket) os_socket_close(bh_socket_t socket)
{ {
@ -164,8 +182,7 @@ os_socket_shutdown(bh_socket_t socket)
} }
int int
os_socket_inet_network(bool is_ipv4, const char *cp, os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out)
bh_inet_network_output_t *out)
{ {
if (!cp) if (!cp)
return BHT_ERROR; return BHT_ERROR;
@ -201,8 +218,7 @@ os_socket_addr_resolve(const char *host, const char *service,
} }
int int
os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen, os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
uint16_t *port, uint8_t *is_ipv4)
{ {
errno = ENOSYS; errno = ENOSYS;
@ -242,8 +258,7 @@ os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us)
} }
int int
os_socket_addr_remote(bh_socket_t socket, uint8_t *buf, size_t buflen, os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr)
uint16_t *port, uint8_t *is_ipv4)
{ {
errno = ENOSYS; errno = ENOSYS;

View File

@ -105,6 +105,10 @@ add_executable(addr_resolve ${CMAKE_CURRENT_SOURCE_DIR}/wasm-src/addr_resolve.c)
add_executable(socket_opts ${CMAKE_CURRENT_SOURCE_DIR}/wasm-src/socket_opts.c) add_executable(socket_opts ${CMAKE_CURRENT_SOURCE_DIR}/wasm-src/socket_opts.c)
add_executable(udp_client ${CMAKE_CURRENT_SOURCE_DIR}/wasm-src/udp_client.c)
add_executable(udp_server ${CMAKE_CURRENT_SOURCE_DIR}/wasm-src/udp_server.c)
############################################ ############################################
## Build iwasm with wasi and pthread support ## Build iwasm with wasi and pthread support
############################################ ############################################

View File

@ -81,3 +81,5 @@ compile_with_clang(tcp_client.c)
compile_with_clang(send_recv.c) compile_with_clang(send_recv.c)
compile_with_clang(addr_resolve.c) compile_with_clang(addr_resolve.c)
compile_with_clang(socket_opts.c) compile_with_clang(socket_opts.c)
compile_with_clang(udp_client.c)
compile_with_clang(udp_server.c)

View File

@ -2,7 +2,7 @@
* Copyright (C) 2019 Intel Corporation. All rights reserved. * Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/ */
#include "tcp_utils.h" #include "socket_utils.h"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>

View File

@ -2,7 +2,7 @@
* Copyright (C) 2019 Intel Corporation. All rights reserved. * Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/ */
#include "tcp_utils.h" #include "socket_utils.h"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>

View File

@ -0,0 +1,82 @@
/*
* Copyright (C) 2022 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#ifdef __wasi__
#include <wasi_socket_ext.h>
#endif
static void
init_sockaddr_inet(struct sockaddr_in *addr)
{
/* 127.0.0.1:1234 */
addr->sin_family = AF_INET;
addr->sin_port = htons(1234);
addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
}
static void
init_sockaddr_inet6(struct sockaddr_in6 *addr)
{
/* [::1]:1234 */
addr->sin6_family = AF_INET6;
addr->sin6_port = htons(1234);
addr->sin6_addr = in6addr_loopback;
}
int
main(int argc, char *argv[])
{
int socket_fd, ret, af;
char buffer[1024] = { 0 };
socklen_t serverlen;
struct sockaddr_storage server_address = { 0 };
const char *message = "Hello from client";
if (argc > 1 && strcmp(argv[1], "inet6") == 0) {
af = AF_INET6;
init_sockaddr_inet6((struct sockaddr_in6 *)&server_address);
serverlen = sizeof(struct sockaddr_in6);
}
else {
af = AF_INET;
init_sockaddr_inet((struct sockaddr_in *)&server_address);
serverlen = sizeof(struct sockaddr_in);
}
printf("[Client] Create socket\n");
socket_fd = socket(af, SOCK_DGRAM, 0);
if (socket_fd == -1) {
perror("Create socket failed");
return EXIT_FAILURE;
}
printf("[Client] Client send\n");
ret = sendto(socket_fd, message, strlen(message), 0,
(struct sockaddr *)&server_address, serverlen);
if (ret < 0) {
close(socket_fd);
perror("Send failed");
return EXIT_FAILURE;
}
printf("[Client] Client receive\n");
serverlen = sizeof(server_address);
ret = recvfrom(socket_fd, buffer, sizeof(buffer), 0,
(struct sockaddr *)&server_address, &serverlen);
if (ret > 0) {
printf("[Client] Buffer recieved: %s\n", buffer);
}
close(socket_fd);
printf("[Client] BYE \n");
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2022 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "socket_utils.h"
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#ifdef __wasi__
#include <wasi_socket_ext.h>
#endif
#define MAX_CONNECTIONS_COUNT 5
static void
init_sockaddr_inet(struct sockaddr_in *addr)
{
/* 0.0.0.0:1234 */
addr->sin_family = AF_INET;
addr->sin_port = htons(1234);
addr->sin_addr.s_addr = htonl(INADDR_ANY);
}
static void
init_sockaddr_inet6(struct sockaddr_in6 *addr)
{
/* [::]:1234 */
addr->sin6_family = AF_INET6;
addr->sin6_port = htons(1234);
addr->sin6_addr = in6addr_any;
}
int
main(int argc, char *argv[])
{
int socket_fd = -1, af;
socklen_t addrlen = 0;
struct sockaddr_storage addr = { 0 };
char *reply_message = "Hello from server";
unsigned connections = 0;
char ip_string[64];
char buffer[1024];
if (argc > 1 && strcmp(argv[1], "inet6") == 0) {
af = AF_INET6;
init_sockaddr_inet6((struct sockaddr_in6 *)&addr);
}
else {
af = AF_INET;
init_sockaddr_inet((struct sockaddr_in *)&addr);
}
printf("[Server] Create socket\n");
socket_fd = socket(af, SOCK_DGRAM, 0);
if (socket_fd < 0) {
perror("Create socket failed");
goto fail;
}
printf("[Server] Bind socket\n");
addrlen = sizeof(addr);
if (bind(socket_fd, (struct sockaddr *)&addr, addrlen) < 0) {
perror("Bind failed");
goto fail;
}
printf("[Server] Wait for clients to connect ..\n");
while (connections < MAX_CONNECTIONS_COUNT) {
int ret = recvfrom(socket_fd, buffer, sizeof(buffer), 0,
(struct sockaddr *)&addr, &addrlen);
if (ret < 0) {
perror("Read failed");
goto fail;
}
if (sockaddr_to_string((struct sockaddr *)&addr, ip_string,
sizeof(ip_string) / sizeof(ip_string[0]))
!= 0) {
printf("[Server] failed to parse client address\n");
goto fail;
}
printf("[Server] received %d bytes from %s: %s\n", ret, ip_string,
buffer);
if (sendto(socket_fd, reply_message, strlen(reply_message), 0,
(struct sockaddr *)&addr, addrlen)
< 0) {
perror("Send failed");
break;
}
connections++;
}
if (connections == MAX_CONNECTIONS_COUNT) {
printf("[Server] Achieve maximum amount of connections\n");
}
printf("[Server] Shuting down ..\n");
shutdown(socket_fd, SHUT_RDWR);
close(socket_fd);
sleep(3);
printf("[Server] BYE \n");
return EXIT_SUCCESS;
fail:
printf("[Server] Shuting down ..\n");
if (socket_fd >= 0)
close(socket_fd);
sleep(3);
return EXIT_FAILURE;
}