mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-06-15 09:39:13 +00:00
Enhance sock_addr_local syscall (#1320)
Slightly change the __wasi_sock_addr_local interface - since we already have a `__wasi_addr_t` structure which is an union, there's no need for passing the length around - the address buffer will always have the right length (i.e. max of all address families).
This commit is contained in:
parent
08fd714551
commit
3e77b053c3
|
@ -114,6 +114,9 @@ sendmsg(int sockfd, const struct msghdr *msg, int flags);
|
||||||
|
|
||||||
int
|
int
|
||||||
socket(int domain, int type, int protocol);
|
socket(int domain, int type, int protocol);
|
||||||
|
|
||||||
|
int
|
||||||
|
getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -141,16 +144,15 @@ __wasi_sock_accept(__wasi_fd_t fd, __wasi_fd_t *fd_new)
|
||||||
* either IP4 or IP6.
|
* either IP4 or IP6.
|
||||||
*/
|
*/
|
||||||
int32_t
|
int32_t
|
||||||
__imported_wasi_snapshot_preview1_sock_addr_local(int32_t arg0, int32_t arg1,
|
__imported_wasi_snapshot_preview1_sock_addr_local(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_local")));
|
__import_name__("sock_addr_local")));
|
||||||
|
|
||||||
static inline __wasi_errno_t
|
static inline __wasi_errno_t
|
||||||
__wasi_sock_addr_local(__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len)
|
__wasi_sock_addr_local(__wasi_fd_t fd, __wasi_addr_t *addr)
|
||||||
{
|
{
|
||||||
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_local(
|
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_local(
|
||||||
(int32_t)fd, (int32_t)buf, (int32_t)buf_len);
|
(int32_t)fd, (int32_t)addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -54,6 +54,38 @@ sockaddr_to_wasi_addr(const struct sockaddr *sock_addr, socklen_t addrlen,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __wasi_errno_t
|
||||||
|
wasi_addr_to_sockaddr(const __wasi_addr_t *wasi_addr,
|
||||||
|
struct sockaddr *sock_addr, socklen_t *addrlen)
|
||||||
|
{
|
||||||
|
switch (wasi_addr->kind) {
|
||||||
|
case IPv4:
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
sock_addr_in.sin_family = AF_INET;
|
||||||
|
sock_addr_in.sin_addr.s_addr = htonl(s_addr);
|
||||||
|
sock_addr_in.sin_port = htons(wasi_addr->addr.ip4.port);
|
||||||
|
memcpy(sock_addr, &sock_addr_in, sizeof(sock_addr_in));
|
||||||
|
|
||||||
|
*addrlen = sizeof(sock_addr_in);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IPv6:
|
||||||
|
// TODO: IPV6
|
||||||
|
return __WASI_ERRNO_AFNOSUPPORT;
|
||||||
|
default:
|
||||||
|
return __WASI_ERRNO_AFNOSUPPORT;
|
||||||
|
}
|
||||||
|
return __WASI_ERRNO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static __wasi_errno_t
|
static __wasi_errno_t
|
||||||
sock_addr_remote(__wasi_fd_t fd, struct sockaddr *sock_addr, socklen_t *addrlen)
|
sock_addr_remote(__wasi_fd_t fd, struct sockaddr *sock_addr, socklen_t *addrlen)
|
||||||
{
|
{
|
||||||
|
@ -67,30 +99,7 @@ sock_addr_remote(__wasi_fd_t fd, struct sockaddr *sock_addr, socklen_t *addrlen)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IPv4 == wasi_addr.kind) {
|
return wasi_addr_to_sockaddr(&wasi_addr, sock_addr, addrlen);
|
||||||
struct sockaddr_in sock_addr_in = { 0 };
|
|
||||||
|
|
||||||
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);
|
|
||||||
sock_addr_in.sin_port = htons(wasi_addr.addr.ip4.port);
|
|
||||||
memcpy(sock_addr, &sock_addr_in, sizeof(sock_addr_in));
|
|
||||||
|
|
||||||
*addrlen = sizeof(sock_addr_in);
|
|
||||||
}
|
|
||||||
else if (IPv6 == wasi_addr.kind) {
|
|
||||||
// TODO: IPV6
|
|
||||||
return __WASI_ERRNO_AFNOSUPPORT;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return __WASI_ERRNO_AFNOSUPPORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return __WASI_ERRNO_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -260,3 +269,18 @@ socket(int domain, int type, int protocol)
|
||||||
|
|
||||||
return sockfd;
|
return sockfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
||||||
|
{
|
||||||
|
__wasi_addr_t wasi_addr = { 0 };
|
||||||
|
__wasi_errno_t error;
|
||||||
|
|
||||||
|
error = __wasi_sock_addr_local(sockfd, &wasi_addr);
|
||||||
|
HANDLE_ERROR(error)
|
||||||
|
|
||||||
|
error = wasi_addr_to_sockaddr(&wasi_addr, addr, addrlen);
|
||||||
|
HANDLE_ERROR(error)
|
||||||
|
|
||||||
|
return __WASI_ERRNO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
|
@ -1009,8 +1009,8 @@ wasi_sock_accept(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_fd_t *fd_new)
|
||||||
}
|
}
|
||||||
|
|
||||||
static wasi_errno_t
|
static wasi_errno_t
|
||||||
wasi_sock_addr_local(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *buf,
|
wasi_sock_addr_local(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);
|
||||||
|
@ -1019,9 +1019,12 @@ wasi_sock_addr_local(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_local(curfds, fd, buf, buf_len);
|
return wasi_ssp_sock_addr_local(curfds, fd, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static wasi_errno_t
|
static wasi_errno_t
|
||||||
|
@ -1401,7 +1404,7 @@ static NativeSymbol native_symbols_libc_wasi[] = {
|
||||||
REG_NATIVE_FUNC(proc_raise, "(i)i"),
|
REG_NATIVE_FUNC(proc_raise, "(i)i"),
|
||||||
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)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)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"),
|
||||||
|
|
|
@ -1007,7 +1007,7 @@ wasi_ssp_sock_addr_local(
|
||||||
#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
|
||||||
|
|
|
@ -203,12 +203,14 @@ convert_clockid(__wasi_clockid_t in, clockid_t *out)
|
||||||
static void
|
static void
|
||||||
ipv4_addr_to_wasi_addr(uint32_t addr, __wasi_ip_port_t port, __wasi_addr_t *out)
|
ipv4_addr_to_wasi_addr(uint32_t addr, __wasi_ip_port_t port, __wasi_addr_t *out)
|
||||||
{
|
{
|
||||||
|
addr = ntohl(addr);
|
||||||
|
|
||||||
out->kind = IPv4;
|
out->kind = IPv4;
|
||||||
out->addr.ip4.port = port;
|
out->addr.ip4.port = port;
|
||||||
out->addr.ip4.addr.n3 = (addr & 0xFF000000) >> 24;
|
out->addr.ip4.addr.n0 = (addr & 0xFF000000) >> 24;
|
||||||
out->addr.ip4.addr.n2 = (addr & 0x00FF0000) >> 16;
|
out->addr.ip4.addr.n1 = (addr & 0x00FF0000) >> 16;
|
||||||
out->addr.ip4.addr.n1 = (addr & 0x0000FF00) >> 8;
|
out->addr.ip4.addr.n2 = (addr & 0x0000FF00) >> 8;
|
||||||
out->addr.ip4.addr.n0 = (addr & 0x000000FF);
|
out->addr.ip4.addr.n3 = (addr & 0x000000FF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts an IPv6 binary address object to WASI address object.
|
// Converts an IPv6 binary address object to WASI address object.
|
||||||
|
@ -2881,16 +2883,34 @@ wasi_ssp_sock_addr_local(
|
||||||
#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_LOCAL, 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_local(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
|
||||||
|
|
|
@ -270,5 +270,54 @@ os_socket_addr_resolve(const char *host, const char *service,
|
||||||
*max_info_size = pos;
|
*max_info_size = pos;
|
||||||
freeaddrinfo(result);
|
freeaddrinfo(result);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
case AF_INET:
|
||||||
|
{
|
||||||
|
struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr_storage;
|
||||||
|
|
||||||
|
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_storage;
|
||||||
|
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;
|
return BHT_OK;
|
||||||
}
|
}
|
|
@ -374,6 +374,25 @@ os_socket_addr_resolve(const char *host, const char *service,
|
||||||
bh_addr_info_t *addr_info, size_t addr_info_size,
|
bh_addr_info_t *addr_info, size_t addr_info_size,
|
||||||
size_t *max_info_size);
|
size_t *max_info_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an binary address and a port of the local socket
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -105,7 +105,7 @@ htonl(uint32 value)
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32
|
uint32
|
||||||
ntohl(uint32 value)
|
ntohl(uint32 value)
|
||||||
{
|
{
|
||||||
return htonl(value);
|
return htonl(value);
|
||||||
|
@ -632,4 +632,13 @@ os_socket_addr_resolve(const char *host, const char *service,
|
||||||
return BHT_ERROR;
|
return BHT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
|
||||||
|
uint16_t *port, uint8_t *is_ipv4)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -95,6 +95,9 @@ struct sockaddr {
|
||||||
char sa_data[14]; /* Address data. */
|
char sa_data[14]; /* Address data. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
ntohl(uint32_t value);
|
||||||
|
|
||||||
int
|
int
|
||||||
socket(int domain, int type, int protocol);
|
socket(int domain, int type, int protocol);
|
||||||
|
|
||||||
|
|
|
@ -171,5 +171,14 @@ os_socket_addr_resolve(const char *host, const char *service,
|
||||||
{
|
{
|
||||||
errno = ENOSYS;
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_addr_local(bh_socket_t socket, uint8_t *buf, size_t buflen,
|
||||||
|
uint16_t *port, uint8_t *is_ipv4)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
return BHT_ERROR;
|
return BHT_ERROR;
|
||||||
}
|
}
|
|
@ -19,7 +19,10 @@ main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int socket_fd, ret, total_size = 0;
|
int socket_fd, ret, total_size = 0;
|
||||||
char buffer[1024] = { 0 };
|
char buffer[1024] = { 0 };
|
||||||
|
char ip_string[16] = { 0 };
|
||||||
struct sockaddr_in server_address = { 0 };
|
struct sockaddr_in server_address = { 0 };
|
||||||
|
struct sockaddr_in local_address = { 0 };
|
||||||
|
socklen_t len;
|
||||||
|
|
||||||
printf("[Client] Create socket\n");
|
printf("[Client] Create socket\n");
|
||||||
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
|
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
@ -42,6 +45,20 @@ main(int argc, char *argv[])
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
len = sizeof(local_address);
|
||||||
|
ret = getsockname(socket_fd, (struct sockaddr *)&local_address, &len);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("Failed to retrieve socket address");
|
||||||
|
close(socket_fd);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
inet_ntop(AF_INET, &local_address.sin_addr, ip_string,
|
||||||
|
sizeof(ip_string) / sizeof(ip_string[0]));
|
||||||
|
|
||||||
|
printf("[Client] Local address is: %s:%d\n", ip_string,
|
||||||
|
ntohs(local_address.sin_port));
|
||||||
|
|
||||||
printf("[Client] Client receive\n");
|
printf("[Client] Client receive\n");
|
||||||
while (1) {
|
while (1) {
|
||||||
ret = recv(socket_fd, buffer + total_size, sizeof(buffer) - total_size,
|
ret = recv(socket_fd, buffer + total_size, sizeof(buffer) - total_size,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user