Implement sock_send_to and sock_recv_from system calls (#1457)
This commit is contained in:
@ -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.
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user