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).
This commit is contained in:
Marcin Kolny 2022-08-08 11:11:28 +02:00 committed by GitHub
parent 3e77b053c3
commit 45136bcc8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 142 additions and 53 deletions

View File

@ -117,6 +117,9 @@ socket(int domain, int type, int protocol);
int int
getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen); getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int
getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
#endif #endif
/** /**
@ -164,16 +167,15 @@ __wasi_sock_addr_local(__wasi_fd_t fd, __wasi_addr_t *addr)
* either IP4 or IP6. * either IP4 or IP6.
*/ */
int32_t int32_t
__imported_wasi_snapshot_preview1_sock_addr_remote(int32_t arg0, int32_t arg1, __imported_wasi_snapshot_preview1_sock_addr_remote(int32_t arg0, int32_t arg1)
int32_t arg2)
__attribute__((__import_module__("wasi_snapshot_preview1"), __attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_addr_remote"))); __import_name__("sock_addr_remote")));
static inline __wasi_errno_t 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( 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);
} }
/** /**

View File

@ -64,10 +64,10 @@ wasi_addr_to_sockaddr(const __wasi_addr_t *wasi_addr,
struct sockaddr_in sock_addr_in = { 0 }; struct sockaddr_in sock_addr_in = { 0 };
uint32_t s_addr; uint32_t s_addr;
s_addr = (wasi_addr.addr.ip4.addr.n0 << 24) s_addr = (wasi_addr->addr.ip4.addr.n0 << 24)
| (wasi_addr.addr.ip4.addr.n1 << 16) | (wasi_addr->addr.ip4.addr.n1 << 16)
| (wasi_addr.addr.ip4.addr.n2 << 8) | (wasi_addr->addr.ip4.addr.n2 << 8)
| wasi_addr.addr.ip4.addr.n3; | wasi_addr->addr.ip4.addr.n3;
sock_addr_in.sin_family = AF_INET; sock_addr_in.sin_family = AF_INET;
sock_addr_in.sin_addr.s_addr = htonl(s_addr); 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; 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 int
accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) 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); error = __wasi_sock_accept(sockfd, &new_sockfd);
HANDLE_ERROR(error) HANDLE_ERROR(error)
// error = sock_addr_remote(new_sockfd, addr, addrlen); error = getpeername(new_sockfd, addr, addrlen);
// HANDLE_ERROR(error) HANDLE_ERROR(error)
*addrlen = 0;
return new_sockfd; return new_sockfd;
} }
@ -284,3 +267,18 @@ getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
return __WASI_ERRNO_SUCCESS; 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;
}

View File

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

View File

@ -1015,7 +1015,7 @@ wasi_ssp_sock_addr_remote(
#if !defined(WASMTIME_SSP_STATIC_CURFDS) #if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, struct fd_table *curfds,
#endif #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__)); ) __attribute__((__warn_unused_result__));
__wasi_errno_t __wasi_errno_t

View File

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

View File

@ -273,28 +273,18 @@ os_socket_addr_resolve(const char *host, const char *service,
return BHT_OK; return BHT_OK;
} }
int static int
os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen, os_socket_convert_sockaddr(struct sockaddr *addr, uint8_t *buf, size_t buflen,
uint16_t *port, uint8_t *is_ipv4) 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(buf);
assert(is_ipv4); assert(is_ipv4);
assert(port); assert(port);
ret = getsockname(socket, (struct sockaddr *)&addr_storage, &addr_len); switch (addr->sa_family) {
if (ret != BHT_OK) {
return BHT_ERROR;
}
switch (addr_storage.ss_family) {
case AF_INET: 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)); assert(buflen >= sizeof(addr_in->sin_addr));
*port = ntohs(addr_in->sin_port); *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: 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)); assert(buflen >= sizeof(addr_in->sin6_addr));
*port = ntohs(addr_in->sin6_port); *port = ntohs(addr_in->sin6_port);
@ -321,3 +311,39 @@ os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
return BHT_OK; 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);
}

View File

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

View File

@ -641,4 +641,13 @@ os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
return BHT_ERROR; 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 #endif

View File

@ -182,3 +182,12 @@ os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
return BHT_ERROR; 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;
}

View File

@ -49,6 +49,7 @@ main(int argc, char *argv[])
unsigned connections = 0; unsigned connections = 0;
pthread_t workers[WORKER_NUM] = { 0 }; pthread_t workers[WORKER_NUM] = { 0 };
int client_sock_fds[WORKER_NUM] = { 0 }; int client_sock_fds[WORKER_NUM] = { 0 };
char ip_string[16];
printf("[Server] Create socket\n"); printf("[Server] Create socket\n");
socket_fd = socket(AF_INET, SOCK_STREAM, 0); socket_fd = socket(AF_INET, SOCK_STREAM, 0);
@ -84,7 +85,11 @@ main(int argc, char *argv[])
break; 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, if (pthread_create(&workers[connections], NULL, run,
&client_sock_fds[connections])) { &client_sock_fds[connections])) {
perror("Create a worker thread failed"); perror("Create a worker thread failed");