Просмотр исходного кода

Implement sock_addr_remote syscall (#1360)

Slightly changed the interface sock_addr_remote - since we already
have a `__wasi_addr_t` structure which is an union, there's no need
for passing length around - the address buffer will always have the
right length (i.e. max of all address families).
Marcin Kolny 3 лет назад
Родитель
Сommit
45136bcc8a

+ 7 - 5
core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h

@@ -117,6 +117,9 @@ socket(int domain, int type, int protocol);
 
 int
 getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+
+int
+getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
 #endif
 
 /**
@@ -164,16 +167,15 @@ __wasi_sock_addr_local(__wasi_fd_t fd, __wasi_addr_t *addr)
  * either IP4 or IP6.
  */
 int32_t
-__imported_wasi_snapshot_preview1_sock_addr_remote(int32_t arg0, int32_t arg1,
-                                                   int32_t arg2)
+__imported_wasi_snapshot_preview1_sock_addr_remote(int32_t arg0, int32_t arg1)
     __attribute__((__import_module__("wasi_snapshot_preview1"),
                    __import_name__("sock_addr_remote")));
 
 static inline __wasi_errno_t
-__wasi_sock_addr_remote(__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len)
+__wasi_sock_addr_remote(__wasi_fd_t fd, __wasi_addr_t *addr)
 {
     return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_remote(
-        (int32_t)fd, (int32_t)buf, (int32_t)buf_len);
+        (int32_t)fd, (int32_t)addr);
 }
 
 /**
@@ -448,4 +450,4 @@ __wasi_sock_set_send_buf_size(__wasi_fd_t fd)
  * since don't want to re-compile the wasi-libc,
  * we tend to keep original implentations of recv() and send().
  */
-#endif
+#endif

+ 21 - 23
core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c

@@ -64,10 +64,10 @@ wasi_addr_to_sockaddr(const __wasi_addr_t *wasi_addr,
             struct sockaddr_in sock_addr_in = { 0 };
             uint32_t s_addr;
 
-            s_addr = (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;
+            s_addr = (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;
 
             sock_addr_in.sin_family = AF_INET;
             sock_addr_in.sin_addr.s_addr = htonl(s_addr);
@@ -86,22 +86,6 @@ wasi_addr_to_sockaddr(const __wasi_addr_t *wasi_addr,
     return __WASI_ERRNO_SUCCESS;
 }
 
-static __wasi_errno_t
-sock_addr_remote(__wasi_fd_t fd, struct sockaddr *sock_addr, socklen_t *addrlen)
-{
-    __wasi_addr_t wasi_addr = { 0 };
-    uint32_t s_addr;
-    __wasi_errno_t error;
-
-    error =
-        __wasi_sock_addr_remote(fd, (uint8_t *)&wasi_addr, sizeof(wasi_addr));
-    if (__WASI_ERRNO_SUCCESS != error) {
-        return error;
-    }
-
-    return wasi_addr_to_sockaddr(&wasi_addr, sock_addr, addrlen);
-}
-
 int
 accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
 {
@@ -112,9 +96,8 @@ accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
     error = __wasi_sock_accept(sockfd, &new_sockfd);
     HANDLE_ERROR(error)
 
-    // error = sock_addr_remote(new_sockfd, addr, addrlen);
-    // HANDLE_ERROR(error)
-    *addrlen = 0;
+    error = getpeername(new_sockfd, addr, addrlen);
+    HANDLE_ERROR(error)
 
     return new_sockfd;
 }
@@ -284,3 +267,18 @@ getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
 
     return __WASI_ERRNO_SUCCESS;
 }
+
+int
+getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+    __wasi_addr_t wasi_addr = { 0 };
+    __wasi_errno_t error;
+
+    error = __wasi_sock_addr_remote(sockfd, &wasi_addr);
+    HANDLE_ERROR(error)
+
+    error = wasi_addr_to_sockaddr(&wasi_addr, addr, addrlen);
+    HANDLE_ERROR(error)
+
+    return __WASI_ERRNO_SUCCESS;
+}

+ 7 - 4
core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c

@@ -1028,8 +1028,8 @@ wasi_sock_addr_local(wasm_exec_env_t exec_env, wasi_fd_t fd,
 }
 
 static wasi_errno_t
-wasi_sock_addr_remote(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *buf,
-                      wasi_size_t buf_len)
+wasi_sock_addr_remote(wasm_exec_env_t exec_env, wasi_fd_t fd,
+                      __wasi_addr_t *addr)
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
@@ -1038,9 +1038,12 @@ wasi_sock_addr_remote(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *buf,
     if (!wasi_ctx)
         return __WASI_EACCES;
 
+    if (!validate_native_addr(addr, sizeof(__wasi_addr_t)))
+        return __WASI_EINVAL;
+
     curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasi_ssp_sock_addr_remote(curfds, fd, buf, buf_len);
+    return wasi_ssp_sock_addr_remote(curfds, fd, addr);
 }
 
 static wasi_errno_t
@@ -1405,7 +1408,7 @@ static NativeSymbol native_symbols_libc_wasi[] = {
     REG_NATIVE_FUNC(random_get, "(*~)i"),
     REG_NATIVE_FUNC(sock_accept, "(i*)i"),
     REG_NATIVE_FUNC(sock_addr_local, "(i*)i"),
-    REG_NATIVE_FUNC(sock_addr_remote, "(i*i)i"),
+    REG_NATIVE_FUNC(sock_addr_remote, "(i*)i"),
     REG_NATIVE_FUNC(sock_addr_resolve, "($$**i*)i"),
     REG_NATIVE_FUNC(sock_bind, "(i*)i"),
     REG_NATIVE_FUNC(sock_close, "(i)i"),

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

@@ -1015,7 +1015,7 @@ wasi_ssp_sock_addr_remote(
 #if !defined(WASMTIME_SSP_STATIC_CURFDS)
     struct fd_table *curfds,
 #endif
-    __wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len
+    __wasi_fd_t fd, __wasi_addr_t *addr
 ) __attribute__((__warn_unused_result__));
 
 __wasi_errno_t

+ 21 - 3
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c

@@ -2918,16 +2918,34 @@ wasi_ssp_sock_addr_remote(
 #if !defined(WASMTIME_SSP_STATIC_CURFDS)
     struct fd_table *curfds,
 #endif
-    __wasi_fd_t fd, uint8 *buf, __wasi_size_t buf_len)
+    __wasi_fd_t fd, __wasi_addr_t *addr)
 {
     struct fd_object *fo;
+    uint8 buf[16];
+    __wasi_ip_port_t port;
+    uint8 is_ipv4;
+    int ret;
+
     __wasi_errno_t error =
-        fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_REMOTE, 0);
+        fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_LOCAL, 0);
     if (error != __WASI_ESUCCESS)
         return error;
 
+    ret = os_socket_addr_remote(fd_number(fo), buf,
+                                sizeof(buf) / sizeof(buf[0]), &port, &is_ipv4);
     fd_object_release(fo);
-    return __WASI_ENOSYS;
+    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);
+    }
+
+    return __WASI_ESUCCESS;
 }
 
 __wasi_errno_t

+ 42 - 16
core/shared/platform/common/posix/posix_socket.c

@@ -273,28 +273,18 @@ os_socket_addr_resolve(const char *host, const char *service,
     return BHT_OK;
 }
 
-int
-os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
-                     uint16_t *port, uint8_t *is_ipv4)
+static int
+os_socket_convert_sockaddr(struct sockaddr *addr, uint8_t *buf, size_t buflen,
+                           uint16_t *port, uint8_t *is_ipv4)
 {
-    struct sockaddr_storage addr_storage = { 0 };
-    socklen_t addr_len = sizeof(addr_storage);
-    int ret;
-
     assert(buf);
     assert(is_ipv4);
     assert(port);
 
-    ret = getsockname(socket, (struct sockaddr *)&addr_storage, &addr_len);
-
-    if (ret != BHT_OK) {
-        return BHT_ERROR;
-    }
-
-    switch (addr_storage.ss_family) {
+    switch (addr->sa_family) {
         case AF_INET:
         {
-            struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr_storage;
+            struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
 
             assert(buflen >= sizeof(addr_in->sin_addr));
             *port = ntohs(addr_in->sin_port);
@@ -304,7 +294,7 @@ os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
         }
         case AF_INET6:
         {
-            struct sockaddr_in6 *addr_in = (struct sockaddr_in6 *)&addr_storage;
+            struct sockaddr_in6 *addr_in = (struct sockaddr_in6 *)addr;
             assert(buflen >= sizeof(addr_in->sin6_addr));
             *port = ntohs(addr_in->sin6_port);
 
@@ -320,4 +310,40 @@ os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
     }
 
     return BHT_OK;
+}
+
+int
+os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
+                     uint16_t *port, uint8_t *is_ipv4)
+{
+    struct sockaddr_storage addr_storage = { 0 };
+    socklen_t addr_len = sizeof(addr_storage);
+    int ret;
+
+    ret = getsockname(socket, (struct sockaddr *)&addr_storage, &addr_len);
+
+    if (ret != BHT_OK) {
+        return BHT_ERROR;
+    }
+
+    return os_socket_convert_sockaddr((struct sockaddr *)&addr_storage, buf,
+                                      buflen, port, is_ipv4);
+}
+
+int
+os_socket_addr_remote(bh_socket_t socket, uint8_t *buf, size_t buflen,
+                      uint16_t *port, uint8_t *is_ipv4)
+{
+    struct sockaddr_storage addr_storage = { 0 };
+    socklen_t addr_len = sizeof(addr_storage);
+    int ret;
+
+    ret = getpeername(socket, (struct sockaddr *)&addr_storage, &addr_len);
+
+    if (ret != BHT_OK) {
+        return BHT_ERROR;
+    }
+
+    return os_socket_convert_sockaddr((struct sockaddr *)&addr_storage, buf,
+                                      buflen, port, is_ipv4);
 }

+ 19 - 0
core/shared/platform/include/platform_api_extension.h

@@ -393,6 +393,25 @@ int
 os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
                      uint16_t *port, uint8_t *is_ipv4);
 
+/**
+ * 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
+ *
+ * @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);
+
 #ifdef __cplusplus
 }
 #endif

+ 9 - 0
core/shared/platform/linux-sgx/sgx_socket.c

@@ -641,4 +641,13 @@ os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
     return BHT_ERROR;
 }
 
+int
+os_socket_addr_remote(bh_socket_t socket, uint8_t *buf, size_t buflen,
+                      uint16_t *port, uint8_t *is_ipv4)
+{
+    errno = ENOSYS;
+
+    return BHT_ERROR;
+}
+
 #endif

+ 9 - 0
core/shared/platform/windows/win_socket.c

@@ -180,5 +180,14 @@ os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
 {
     errno = ENOSYS;
 
+    return BHT_ERROR;
+}
+
+int
+os_socket_addr_remote(bh_socket_t socket, uint8_t *buf, size_t buflen,
+                      uint16_t *port, uint8_t *is_ipv4)
+{
+    errno = ENOSYS;
+
     return BHT_ERROR;
 }

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

@@ -49,6 +49,7 @@ main(int argc, char *argv[])
     unsigned connections = 0;
     pthread_t workers[WORKER_NUM] = { 0 };
     int client_sock_fds[WORKER_NUM] = { 0 };
+    char ip_string[16];
 
     printf("[Server] Create socket\n");
     socket_fd = socket(AF_INET, SOCK_STREAM, 0);
@@ -84,7 +85,11 @@ main(int argc, char *argv[])
             break;
         }
 
-        printf("[Server] Client connected\n");
+        inet_ntop(AF_INET, &addr.sin_addr, ip_string,
+                  sizeof(ip_string) / sizeof(ip_string[0]));
+
+        printf("[Server] Client connected (%s:%d)\n", ip_string,
+               ntohs(addr.sin_port));
         if (pthread_create(&workers[connections], NULL, run,
                            &client_sock_fds[connections])) {
             perror("Create a worker thread failed");