Added socket send and recv timeout options (#1419)
Added socket send and recv timeout options with implementation for posix platform. This is part of a extending support for sockets in WASI. #1336. Also add sample that sets and reads back the send and receive timeouts using the native function binding.
This commit is contained in:
@ -94,6 +94,9 @@ typedef struct __wasi_addr_info_hints_t {
|
||||
* <sys/types.h>
|
||||
*/
|
||||
|
||||
#define SO_RCVTIMEO 20
|
||||
#define SO_SNDTIMEO 21
|
||||
|
||||
struct addrinfo {
|
||||
int ai_flags; /* Input flags. */
|
||||
int ai_family; /* Protocol family for socket. */
|
||||
@ -132,6 +135,14 @@ getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
|
||||
int
|
||||
getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
|
||||
|
||||
int
|
||||
getsockopt(int sockfd, int level, int optname, void *__restrict optval,
|
||||
socklen_t *__restrict optlen);
|
||||
|
||||
int
|
||||
setsockopt(int sockfd, int level, int optname, const void *optval,
|
||||
socklen_t optlen);
|
||||
|
||||
int
|
||||
getaddrinfo(const char *node, const char *service, const struct addrinfo *hints,
|
||||
struct addrinfo **res);
|
||||
@ -463,6 +474,62 @@ __wasi_sock_set_send_buf_size(__wasi_fd_t fd)
|
||||
__imported_wasi_snapshot_preview1_sock_set_send_buf_size((int32_t)fd);
|
||||
}
|
||||
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_get_recv_timeout(int32_t arg0,
|
||||
int32_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_get_recv_timeout")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_get_recv_timeout(__wasi_fd_t fd, uint64_t *timeout_us)
|
||||
{
|
||||
return (__wasi_errno_t)
|
||||
__imported_wasi_snapshot_preview1_sock_get_recv_timeout(
|
||||
(int32_t)fd, (int32_t)timeout_us);
|
||||
}
|
||||
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_set_recv_timeout(int32_t arg0,
|
||||
int64_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_set_recv_timeout")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_set_recv_timeout(__wasi_fd_t fd, uint64_t timeout_us)
|
||||
{
|
||||
return (__wasi_errno_t)
|
||||
__imported_wasi_snapshot_preview1_sock_set_recv_timeout(
|
||||
(int32_t)fd, (int64_t)timeout_us);
|
||||
}
|
||||
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_get_send_timeout(int32_t arg0,
|
||||
int32_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_get_send_timeout")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_get_send_timeout(__wasi_fd_t fd, uint64_t *timeout_us)
|
||||
{
|
||||
return (__wasi_errno_t)
|
||||
__imported_wasi_snapshot_preview1_sock_get_send_timeout(
|
||||
(int32_t)fd, (int32_t)timeout_us);
|
||||
}
|
||||
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_set_send_timeout(int32_t arg0,
|
||||
int64_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_set_send_timeout")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_set_send_timeout(__wasi_fd_t fd, uint64_t timeout_us)
|
||||
{
|
||||
return (__wasi_errno_t)
|
||||
__imported_wasi_snapshot_preview1_sock_set_send_timeout(
|
||||
(int32_t)fd, (int64_t)timeout_us);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: modify recv() and send()
|
||||
* since don't want to re-compile the wasi-libc,
|
||||
|
||||
@ -469,4 +469,93 @@ freeaddrinfo(struct addrinfo *res)
|
||||
* of aibuf array allocated in getaddrinfo, therefore this call
|
||||
* frees the memory of the entire array. */
|
||||
free(res);
|
||||
}
|
||||
}
|
||||
|
||||
struct timeval
|
||||
time_us_to_timeval(uint64_t time_us)
|
||||
{
|
||||
struct timeval tv;
|
||||
tv.tv_sec = time_us / 1000000UL;
|
||||
tv.tv_usec = time_us % 1000000UL;
|
||||
return tv;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
timeval_to_time_us(struct timeval tv)
|
||||
{
|
||||
return (tv.tv_sec * 1000000UL) + tv.tv_usec;
|
||||
}
|
||||
|
||||
int
|
||||
get_sol_socket_option(int sockfd, int optname, void *__restrict optval,
|
||||
socklen_t *__restrict optlen)
|
||||
{
|
||||
__wasi_errno_t error;
|
||||
uint64_t timeout_us;
|
||||
|
||||
switch (optname) {
|
||||
case SO_RCVTIMEO:
|
||||
assert(*optlen == sizeof(struct timeval));
|
||||
error = __wasi_sock_get_recv_timeout(sockfd, &timeout_us);
|
||||
HANDLE_ERROR(error);
|
||||
*(struct timeval *)optval = time_us_to_timeval(timeout_us);
|
||||
return error;
|
||||
case SO_SNDTIMEO:
|
||||
assert(*optlen == sizeof(struct timeval));
|
||||
error = __wasi_sock_get_send_timeout(sockfd, &timeout_us);
|
||||
HANDLE_ERROR(error);
|
||||
*(struct timeval *)optval = time_us_to_timeval(timeout_us);
|
||||
return error;
|
||||
}
|
||||
|
||||
HANDLE_ERROR(__WASI_ERRNO_NOTSUP);
|
||||
}
|
||||
|
||||
int
|
||||
getsockopt(int sockfd, int level, int optname, void *__restrict optval,
|
||||
socklen_t *__restrict optlen)
|
||||
{
|
||||
switch (level) {
|
||||
case SOL_SOCKET:
|
||||
return get_sol_socket_option(sockfd, optname, optval, optlen);
|
||||
}
|
||||
|
||||
HANDLE_ERROR(__WASI_ERRNO_NOTSUP);
|
||||
}
|
||||
|
||||
int
|
||||
set_sol_socket_option(int sockfd, int optname, const void *optval,
|
||||
socklen_t optlen)
|
||||
{
|
||||
__wasi_errno_t error;
|
||||
uint64_t timeout_us;
|
||||
|
||||
switch (optname) {
|
||||
case SO_RCVTIMEO:
|
||||
assert(optlen == sizeof(struct timeval));
|
||||
timeout_us = timeval_to_time_us(*(struct timeval *)optval);
|
||||
error = __wasi_sock_set_recv_timeout(sockfd, timeout_us);
|
||||
HANDLE_ERROR(error);
|
||||
return error;
|
||||
case SO_SNDTIMEO:
|
||||
assert(optlen == sizeof(struct timeval));
|
||||
timeout_us = timeval_to_time_us(*(struct timeval *)optval);
|
||||
error = __wasi_sock_set_send_timeout(sockfd, timeout_us);
|
||||
HANDLE_ERROR(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
HANDLE_ERROR(__WASI_ERRNO_NOTSUP);
|
||||
}
|
||||
|
||||
int
|
||||
setsockopt(int sockfd, int level, int optname, const void *optval,
|
||||
socklen_t optlen)
|
||||
{
|
||||
switch (level) {
|
||||
case SOL_SOCKET:
|
||||
return set_sol_socket_option(sockfd, optname, optval, optlen);
|
||||
}
|
||||
|
||||
HANDLE_ERROR(__WASI_ERRNO_NOTSUP);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user