فهرست منبع

Implement sock_send_to and sock_recv_from system calls (#1457)

Marcin Kolny 3 سال پیش
والد
کامیت
b731ca4668

+ 50 - 0
core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h

@@ -126,6 +126,14 @@ recvmsg(int sockfd, struct msghdr *msg, int flags);
 ssize_t
 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
 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);
 }
 
+/**
+ * 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`)
  * Note: This is similar to `close` in POSIX.

+ 61 - 1
core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c

@@ -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);
     }
     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(
             (uint16_t *)((struct sockaddr_in6 *)sock_addr)->sin6_addr.s6_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;
 }
 
+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
 socket(int domain, int type, int protocol)
 {

+ 174 - 79
core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c

@@ -1274,9 +1274,70 @@ wasi_sock_set_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
 }
 
 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)
+allocate_iovec_app_buffer(wasm_module_inst_t module_inst,
+                          const iovec_app_t *data, uint32 data_len,
+                          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
@@ -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);
     struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     uint64 total_size;
-    uint32 i;
-    iovec_app_t *ri_data_orig = ri_data;
-    uint8 *buf = NULL;
     uint8 *buf_begin = NULL;
     wasi_errno_t err;
     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;
     }
 
-    if (ri_data_len == 0) {
-        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))
+    if (!validate_native_addr(ro_data_len, (uint32)sizeof(uint32)))
         return __WASI_EINVAL;
 
-    /* receive and scatter*/
-    for (total_size = 0, i = 0; i < ri_data_len; i++, ri_data++) {
-        total_size += ri_data->buf_len;
-    }
-    if (total_size >= UINT32_MAX
-        || !(buf_begin = wasm_runtime_malloc((uint32)total_size))) {
-        return __WASI_ENOMEM;
+    err = allocate_iovec_app_buffer(module_inst, ri_data, ri_data_len,
+                                    &buf_begin, &total_size);
+    if (err != __WASI_ESUCCESS) {
+        goto fail;
     }
+
     memset(buf_begin, 0, total_size);
 
     *ro_data_len = 0;
-    err = wasmtime_ssp_sock_recv(curfds, sock, buf_begin, total_size,
-                                 &recv_bytes);
+    err = wasmtime_ssp_sock_recv_from(curfds, sock, buf_begin, total_size,
+                                      ri_flags, src_addr, &recv_bytes);
     if (err != __WASI_ESUCCESS) {
         goto fail;
     }
     *ro_data_len = (uint32)recv_bytes;
 
-    buf = buf_begin;
-    ri_data = ri_data_orig;
-    for (i = 0; i < ri_data_len; ri_data++, i++) {
-        char *native_addr;
-
-        if ((uint32)(buf - buf_begin) >= *ro_data_len) {
-            break;
-        }
+    err = copy_buffer_to_iovec_app(module_inst, buf_begin, (uint32)recv_bytes,
+                                   ri_data, ri_data_len);
 
-        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:
     if (buf_begin) {
         wasm_runtime_free(buf_begin);
@@ -1353,6 +1384,59 @@ fail:
     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
 wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock,
                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);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
     struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
-    uint64 total_size = 0;
-    uint32 i;
-    const iovec_app_t *si_data_orig = si_data;
+    uint64 buf_size = 0;
     uint8 *buf = NULL;
-    uint8 *buf_begin = NULL;
     wasi_errno_t err;
     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;
     }
 
-    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;
+    err = convert_iovec_app_to_buffer(module_inst, si_data, si_data_len, &buf,
+                                      &buf_size);
+    if (err != __WASI_ESUCCESS)
+        return err;
 
-    /* gather and send */
-    for (total_size = 0, i = 0; i < si_data_len; i++, si_data++) {
-        total_size += si_data->buf_len;
-    }
-    if (total_size >= UINT32_MAX
-        || !(buf_begin = wasm_runtime_malloc((uint32)total_size))) {
-        return __WASI_ENOMEM;
-    }
+    *so_data_len = 0;
+    err = wasmtime_ssp_sock_send(curfds, sock, buf, buf_size, &send_bytes);
+    *so_data_len = (uint32)send_bytes;
 
-    buf = buf_begin;
-    si_data = si_data_orig;
-    for (i = 0; i < si_data_len; i++, si_data++) {
-        char *native_addr;
+    wasm_runtime_free(buf);
 
-        if (!validate_app_addr(si_data->buf_offset, si_data->buf_len)) {
-            err = __WASI_EINVAL;
-            goto fail;
-        }
+    return err;
+}
 
-        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;
+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(curfds, sock, buf_begin, total_size,
-                                 &send_bytes);
+    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;
 
-fail:
-    if (buf_begin) {
-        wasm_runtime_free(buf_begin);
-    }
+    wasm_runtime_free(buf);
+
     return err;
 }
 
@@ -1505,7 +1598,9 @@ static NativeSymbol native_symbols_libc_wasi[] = {
     REG_NATIVE_FUNC(sock_listen, "(ii)i"),
     REG_NATIVE_FUNC(sock_open, "(iii*)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_to, "(i*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_reuse_addr, "(ii)i"),

+ 24 - 0
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h

@@ -1071,6 +1071,18 @@ __wasi_errno_t wasmtime_ssp_sock_recv(
     size_t *recv_len
 ) 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(
 #if !defined(WASMTIME_SSP_STATIC_CURFDS)
     struct fd_table *curfds,
@@ -1081,6 +1093,18 @@ __wasi_errno_t wasmtime_ssp_sock_send(
     size_t *sent_len
 ) 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(
 #if !defined(WASMTIME_SSP_STATIC_CURFDS)
     struct fd_table *curfds,

+ 117 - 59
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c

@@ -224,35 +224,59 @@ convert_clockid(__wasi_clockid_t in, clockid_t *out)
     }
 }
 
-// Converts an IPv4 binary address object to WASI address.
 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);
-
-    out->kind = IPv4;
-    out->addr.ip4.port = port;
-    out->addr.ip4.addr.n0 = (addr & 0xFF000000) >> 24;
-    out->addr.ip4.addr.n1 = (addr & 0x00FF0000) >> 16;
-    out->addr.ip4.addr.n2 = (addr & 0x0000FF00) >> 8;
-    out->addr.ip4.addr.n3 = (addr & 0x000000FF);
+    if (wasi_addr->kind == IPv4) {
+        sockaddr->addr_bufer.ipv4 = (wasi_addr->addr.ip4.addr.n0 << 24)
+                                    | (wasi_addr->addr.ip4.addr.n1 << 16)
+                                    | (wasi_addr->addr.ip4.addr.n2 << 8)
+                                    | wasi_addr->addr.ip4.addr.n3;
+        sockaddr->is_ipv4 = true;
+        sockaddr->port = wasi_addr->addr.ip4.port;
+    }
+    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
-ipv6_addr_to_wasi_addr(uint16_t addr[8], __wasi_ip_port_t port,
-                       __wasi_addr_t *out)
-{
-    out->kind = IPv6;
-    out->addr.ip6.port = port;
-    out->addr.ip6.addr.n0 = addr[0];
-    out->addr.ip6.addr.n1 = addr[1];
-    out->addr.ip6.addr.n2 = addr[2];
-    out->addr.ip6.addr.n3 = addr[3];
-    out->addr.ip6.addr.h0 = addr[4];
-    out->addr.ip6.addr.h1 = addr[5];
-    out->addr.ip6.addr.h2 = addr[6];
-    out->addr.ip6.addr.h3 = addr[7];
+bh_sockaddr_to_wasi_addr(const bh_sockaddr_t *sockaddr,
+                         __wasi_addr_t *wasi_addr)
+{
+    if (sockaddr->is_ipv4) {
+        wasi_addr->kind = IPv4;
+        wasi_addr->addr.ip4.port = sockaddr->port;
+        wasi_addr->addr.ip4.addr.n0 =
+            (sockaddr->addr_bufer.ipv4 & 0xFF000000) >> 24;
+        wasi_addr->addr.ip4.addr.n1 =
+            (sockaddr->addr_bufer.ipv4 & 0x00FF0000) >> 16;
+        wasi_addr->addr.ip4.addr.n2 =
+            (sockaddr->addr_bufer.ipv4 & 0x0000FF00) >> 8;
+        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
@@ -2911,9 +2935,7 @@ wasi_ssp_sock_addr_local(
     __wasi_fd_t fd, __wasi_addr_t *addr)
 {
     struct fd_object *fo;
-    uint8 buf[16];
-    __wasi_ip_port_t port;
-    uint8 is_ipv4;
+    bh_sockaddr_t bh_addr;
     int ret;
 
     __wasi_errno_t error =
@@ -2921,19 +2943,13 @@ wasi_ssp_sock_addr_local(
     if (error != __WASI_ESUCCESS)
         return error;
 
-    ret = os_socket_addr_local(fd_number(fo), buf, sizeof(buf) / sizeof(buf[0]),
-                               &port, &is_ipv4);
+    ret = os_socket_addr_local(fd_number(fo), &bh_addr);
     fd_object_release(fo);
     if (ret != BHT_OK) {
         return convert_errno(errno);
     }
 
-    if (is_ipv4) {
-        ipv4_addr_to_wasi_addr(*(uint32_t *)buf, port, addr);
-    }
-    else {
-        ipv6_addr_to_wasi_addr((uint16 *)buf, port, addr);
-    }
+    bh_sockaddr_to_wasi_addr(&bh_addr, addr);
 
     return __WASI_ESUCCESS;
 }
@@ -2946,9 +2962,7 @@ wasi_ssp_sock_addr_remote(
     __wasi_fd_t fd, __wasi_addr_t *addr)
 {
     struct fd_object *fo;
-    uint8 buf[16];
-    __wasi_ip_port_t port;
-    uint8 is_ipv4;
+    bh_sockaddr_t bh_addr;
     int ret;
 
     __wasi_errno_t error =
@@ -2956,25 +2970,19 @@ wasi_ssp_sock_addr_remote(
     if (error != __WASI_ESUCCESS)
         return error;
 
-    ret = os_socket_addr_remote(fd_number(fo), buf,
-                                sizeof(buf) / sizeof(buf[0]), &port, &is_ipv4);
+    ret = os_socket_addr_remote(fd_number(fo), &bh_addr);
     fd_object_release(fo);
     if (ret != BHT_OK) {
         return convert_errno(errno);
     }
 
-    if (is_ipv4) {
-        ipv4_addr_to_wasi_addr(*(uint32_t *)buf, port, addr);
-    }
-    else {
-        ipv6_addr_to_wasi_addr((uint16 *)buf, port, addr);
-    }
+    bh_sockaddr_to_wasi_addr(&bh_addr, addr);
 
     return __WASI_ESUCCESS;
 }
 
 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) {
         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++) {
         addr_info[i].type =
             wamr_addr_info[i].is_tcp ? SOCKET_STREAM : SOCKET_DGRAM;
-        if (wamr_addr_info[i].is_ipv4) {
-            ipv4_addr_to_wasi_addr(*(uint32_t *)wamr_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);
-        }
+        bh_sockaddr_to_wasi_addr(&wamr_addr_info[i].sockaddr,
+                                 &addr_info[i].addr);
     }
 
     wasm_runtime_free(wamr_addr_info);
@@ -3202,9 +3204,24 @@ wasmtime_ssp_sock_recv(
     struct fd_table *curfds,
 #endif
     __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;
     __wasi_errno_t error;
+    bh_sockaddr_t sockaddr;
     int ret;
 
     error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_READ, 0);
@@ -3212,12 +3229,14 @@ wasmtime_ssp_sock_recv(
         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);
     if (-1 == ret) {
         return convert_errno(errno);
     }
 
+    bh_sockaddr_to_wasi_addr(&sockaddr, src_addr);
+
     *recv_len = (size_t)ret;
     return __WASI_ESUCCESS;
 }
@@ -3248,6 +3267,45 @@ wasmtime_ssp_sock_send(
     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
 wasmtime_ssp_sock_shutdown(
 #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 *next;
-    bh_inet_network_output_t target;
+    bh_ip_addr_buffer_t target;
 
     if (!addr_pool) {
         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 */
 static bool
 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 basebuf[16] = { 0 };
@@ -3515,7 +3573,7 @@ bool
 addr_pool_search(struct addr_pool *addr_pool, const char *addr)
 {
     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;
 
     if (os_socket_inet_network(true, addr, &target) != BHT_OK) {

+ 116 - 69
core/shared/platform/common/posix/posix_socket.c

@@ -34,6 +34,77 @@ textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr *out)
     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
 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);
 }
 
+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
 os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
 {
     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
 os_socket_close(bh_socket_t socket)
 {
@@ -189,8 +296,7 @@ os_socket_shutdown(bh_socket_t socket)
 }
 
 int
-os_socket_inet_network(bool is_ipv4, const char *cp,
-                       bh_inet_network_output_t *out)
+os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out)
 {
     if (!cp)
         return BHT_ERROR;
@@ -278,26 +384,8 @@ os_socket_addr_resolve(const char *host, const char *service,
                 continue;
             }
 
-            if (res->ai_family == AF_INET) {
-                struct sockaddr_in *addr_in =
-                    (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]);
-                }
-            }
+            sockaddr_to_bh_sockaddr(res->ai_addr, sizeof(struct sockaddr_in),
+                                    &addr_info[pos].sockaddr);
 
             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;
 }
 
-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
 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
-os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
-                     uint16_t *port, uint8_t *is_ipv4)
+os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
 {
     struct sockaddr_storage addr_storage = { 0 };
     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 os_socket_convert_sockaddr((struct sockaddr *)&addr_storage, buf,
-                                      buflen, port, is_ipv4);
+    return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr_storage, addr_len,
+                                   sockaddr);
 }
 
 int
-os_socket_addr_remote(bh_socket_t socket, uint8_t *buf, size_t buflen,
-                      uint16_t *port, uint8_t *is_ipv4)
+os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr)
 {
     struct sockaddr_storage addr_storage = { 0 };
     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 os_socket_convert_sockaddr((struct sockaddr *)&addr_storage, buf,
-                                      buflen, port, is_ipv4);
+    return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr_storage, addr_len,
+                                   sockaddr);
 }

+ 49 - 29
core/shared/platform/include/platform_api_extension.h

@@ -292,6 +292,18 @@ os_sem_unlink(const char *name);
  * 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
  *
@@ -381,6 +393,22 @@ os_socket_connect(bh_socket_t socket, const char *addr, int port);
 int
 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
  *
@@ -393,6 +421,21 @@ os_socket_recv(bh_socket_t socket, void *buf, unsigned int len);
 int
 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
  *
@@ -413,12 +456,6 @@ os_socket_close(bh_socket_t socket);
 int
 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
  * an Internet network address
@@ -435,13 +472,10 @@ typedef union {
  * If the input is invalid, -1 is returned
  */
 int
-os_socket_inet_network(bool is_ipv4, const char *cp,
-                       bh_inet_network_output_t *out);
+os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out);
 
 typedef struct {
-    uint8_t addr[16];
-    uint16_t port;
-    uint8_t is_ipv4;
+    bh_sockaddr_t sockaddr;
     uint8_t is_tcp;
 } bh_addr_info_t;
 
@@ -478,38 +512,24 @@ os_socket_addr_resolve(const char *host, const char *service,
  *
  * @param socket the local socket
  *
- * @param buf buffer to store 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
+ * @param sockaddr a buffer for storing the address
  *
  * @return On success, returns 0; otherwise, it returns -1.
  */
 int
-os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
-                     uint16_t *port, uint8_t *is_ipv4);
+os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr);
 
 /**
  * Returns an binary address and a port of the remote socket
  *
  * @param socket the remote socket
  *
- * @param buf buffer to store 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
+ * @param sockaddr a buffer for storing the address
  *
  * @return On success, returns 0; otherwise, it returns -1.
  */
 int
-os_socket_addr_remote(bh_socket_t socket, uint8_t *buf, size_t buflen,
-                      uint16_t *port, uint8_t *is_ipv4);
+os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr);
 
 /**
  * Set the send timeout until reporting an error

+ 21 - 6
core/shared/platform/linux-sgx/sgx_socket.c

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

+ 21 - 6
core/shared/platform/windows/win_socket.c

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

+ 4 - 0
samples/socket-api/CMakeLists.txt

@@ -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(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
 ############################################

+ 2 - 0
samples/socket-api/wasm-src/CMakeLists.txt

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

+ 0 - 0
samples/socket-api/wasm-src/tcp_utils.h → samples/socket-api/wasm-src/socket_utils.h


+ 1 - 1
samples/socket-api/wasm-src/tcp_client.c

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

+ 1 - 1
samples/socket-api/wasm-src/tcp_server.c

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

+ 82 - 0
samples/socket-api/wasm-src/udp_client.c

@@ -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;
+}

+ 118 - 0
samples/socket-api/wasm-src/udp_server.c

@@ -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;
+}