Skip to content

Commit 72367f4

Browse files
authored
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.
1 parent 3c4e980 commit 72367f4

File tree

13 files changed

+526
-1
lines changed

13 files changed

+526
-1
lines changed

core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ typedef struct __wasi_addr_info_hints_t {
9494
* <sys/types.h>
9595
*/
9696

97+
#define SO_RCVTIMEO 20
98+
#define SO_SNDTIMEO 21
99+
97100
struct addrinfo {
98101
int ai_flags; /* Input flags. */
99102
int ai_family; /* Protocol family for socket. */
@@ -132,6 +135,14 @@ getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
132135
int
133136
getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
134137

138+
int
139+
getsockopt(int sockfd, int level, int optname, void *__restrict optval,
140+
socklen_t *__restrict optlen);
141+
142+
int
143+
setsockopt(int sockfd, int level, int optname, const void *optval,
144+
socklen_t optlen);
145+
135146
int
136147
getaddrinfo(const char *node, const char *service, const struct addrinfo *hints,
137148
struct addrinfo **res);
@@ -463,6 +474,62 @@ __wasi_sock_set_send_buf_size(__wasi_fd_t fd)
463474
__imported_wasi_snapshot_preview1_sock_set_send_buf_size((int32_t)fd);
464475
}
465476

477+
int32_t
478+
__imported_wasi_snapshot_preview1_sock_get_recv_timeout(int32_t arg0,
479+
int32_t arg1)
480+
__attribute__((__import_module__("wasi_snapshot_preview1"),
481+
__import_name__("sock_get_recv_timeout")));
482+
483+
static inline __wasi_errno_t
484+
__wasi_sock_get_recv_timeout(__wasi_fd_t fd, uint64_t *timeout_us)
485+
{
486+
return (__wasi_errno_t)
487+
__imported_wasi_snapshot_preview1_sock_get_recv_timeout(
488+
(int32_t)fd, (int32_t)timeout_us);
489+
}
490+
491+
int32_t
492+
__imported_wasi_snapshot_preview1_sock_set_recv_timeout(int32_t arg0,
493+
int64_t arg1)
494+
__attribute__((__import_module__("wasi_snapshot_preview1"),
495+
__import_name__("sock_set_recv_timeout")));
496+
497+
static inline __wasi_errno_t
498+
__wasi_sock_set_recv_timeout(__wasi_fd_t fd, uint64_t timeout_us)
499+
{
500+
return (__wasi_errno_t)
501+
__imported_wasi_snapshot_preview1_sock_set_recv_timeout(
502+
(int32_t)fd, (int64_t)timeout_us);
503+
}
504+
505+
int32_t
506+
__imported_wasi_snapshot_preview1_sock_get_send_timeout(int32_t arg0,
507+
int32_t arg1)
508+
__attribute__((__import_module__("wasi_snapshot_preview1"),
509+
__import_name__("sock_get_send_timeout")));
510+
511+
static inline __wasi_errno_t
512+
__wasi_sock_get_send_timeout(__wasi_fd_t fd, uint64_t *timeout_us)
513+
{
514+
return (__wasi_errno_t)
515+
__imported_wasi_snapshot_preview1_sock_get_send_timeout(
516+
(int32_t)fd, (int32_t)timeout_us);
517+
}
518+
519+
int32_t
520+
__imported_wasi_snapshot_preview1_sock_set_send_timeout(int32_t arg0,
521+
int64_t arg1)
522+
__attribute__((__import_module__("wasi_snapshot_preview1"),
523+
__import_name__("sock_set_send_timeout")));
524+
525+
static inline __wasi_errno_t
526+
__wasi_sock_set_send_timeout(__wasi_fd_t fd, uint64_t timeout_us)
527+
{
528+
return (__wasi_errno_t)
529+
__imported_wasi_snapshot_preview1_sock_set_send_timeout(
530+
(int32_t)fd, (int64_t)timeout_us);
531+
}
532+
466533
/**
467534
* TODO: modify recv() and send()
468535
* since don't want to re-compile the wasi-libc,

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

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,4 +469,93 @@ freeaddrinfo(struct addrinfo *res)
469469
* of aibuf array allocated in getaddrinfo, therefore this call
470470
* frees the memory of the entire array. */
471471
free(res);
472-
}
472+
}
473+
474+
struct timeval
475+
time_us_to_timeval(uint64_t time_us)
476+
{
477+
struct timeval tv;
478+
tv.tv_sec = time_us / 1000000UL;
479+
tv.tv_usec = time_us % 1000000UL;
480+
return tv;
481+
}
482+
483+
uint64_t
484+
timeval_to_time_us(struct timeval tv)
485+
{
486+
return (tv.tv_sec * 1000000UL) + tv.tv_usec;
487+
}
488+
489+
int
490+
get_sol_socket_option(int sockfd, int optname, void *__restrict optval,
491+
socklen_t *__restrict optlen)
492+
{
493+
__wasi_errno_t error;
494+
uint64_t timeout_us;
495+
496+
switch (optname) {
497+
case SO_RCVTIMEO:
498+
assert(*optlen == sizeof(struct timeval));
499+
error = __wasi_sock_get_recv_timeout(sockfd, &timeout_us);
500+
HANDLE_ERROR(error);
501+
*(struct timeval *)optval = time_us_to_timeval(timeout_us);
502+
return error;
503+
case SO_SNDTIMEO:
504+
assert(*optlen == sizeof(struct timeval));
505+
error = __wasi_sock_get_send_timeout(sockfd, &timeout_us);
506+
HANDLE_ERROR(error);
507+
*(struct timeval *)optval = time_us_to_timeval(timeout_us);
508+
return error;
509+
}
510+
511+
HANDLE_ERROR(__WASI_ERRNO_NOTSUP);
512+
}
513+
514+
int
515+
getsockopt(int sockfd, int level, int optname, void *__restrict optval,
516+
socklen_t *__restrict optlen)
517+
{
518+
switch (level) {
519+
case SOL_SOCKET:
520+
return get_sol_socket_option(sockfd, optname, optval, optlen);
521+
}
522+
523+
HANDLE_ERROR(__WASI_ERRNO_NOTSUP);
524+
}
525+
526+
int
527+
set_sol_socket_option(int sockfd, int optname, const void *optval,
528+
socklen_t optlen)
529+
{
530+
__wasi_errno_t error;
531+
uint64_t timeout_us;
532+
533+
switch (optname) {
534+
case SO_RCVTIMEO:
535+
assert(optlen == sizeof(struct timeval));
536+
timeout_us = timeval_to_time_us(*(struct timeval *)optval);
537+
error = __wasi_sock_set_recv_timeout(sockfd, timeout_us);
538+
HANDLE_ERROR(error);
539+
return error;
540+
case SO_SNDTIMEO:
541+
assert(optlen == sizeof(struct timeval));
542+
timeout_us = timeval_to_time_us(*(struct timeval *)optval);
543+
error = __wasi_sock_set_send_timeout(sockfd, timeout_us);
544+
HANDLE_ERROR(error);
545+
return error;
546+
}
547+
548+
HANDLE_ERROR(__WASI_ERRNO_NOTSUP);
549+
}
550+
551+
int
552+
setsockopt(int sockfd, int level, int optname, const void *optval,
553+
socklen_t optlen)
554+
{
555+
switch (level) {
556+
case SOL_SOCKET:
557+
return set_sol_socket_option(sockfd, optname, optval, optlen);
558+
}
559+
560+
HANDLE_ERROR(__WASI_ERRNO_NOTSUP);
561+
}

core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,6 +1126,25 @@ wasi_sock_get_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
11261126
return __WASI_ENOSYS;
11271127
}
11281128

1129+
static wasi_errno_t
1130+
wasi_sock_get_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
1131+
uint64_t *timeout_us)
1132+
{
1133+
wasm_module_inst_t module_inst = get_module_inst(exec_env);
1134+
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
1135+
struct fd_table *curfds = NULL;
1136+
1137+
if (!wasi_ctx)
1138+
return __WASI_EACCES;
1139+
1140+
if (!validate_native_addr(timeout_us, sizeof(uint64_t)))
1141+
return __WASI_EINVAL;
1142+
1143+
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
1144+
1145+
return wasmtime_ssp_sock_get_recv_timeout(curfds, fd, timeout_us);
1146+
}
1147+
11291148
static wasi_errno_t
11301149
wasi_sock_get_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *reuse)
11311150
{
@@ -1145,6 +1164,25 @@ wasi_sock_get_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
11451164
return __WASI_ENOSYS;
11461165
}
11471166

1167+
static wasi_errno_t
1168+
wasi_sock_get_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
1169+
uint64_t *timeout_us)
1170+
{
1171+
wasm_module_inst_t module_inst = get_module_inst(exec_env);
1172+
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
1173+
struct fd_table *curfds = NULL;
1174+
1175+
if (!wasi_ctx)
1176+
return __WASI_EACCES;
1177+
1178+
if (!validate_native_addr(timeout_us, sizeof(uint64_t)))
1179+
return __WASI_EINVAL;
1180+
1181+
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
1182+
1183+
return wasmtime_ssp_sock_get_send_timeout(curfds, fd, timeout_us);
1184+
}
1185+
11481186
static wasi_errno_t
11491187
wasi_sock_listen(wasm_exec_env_t exec_env, wasi_fd_t fd, uint32 backlog)
11501188
{
@@ -1184,6 +1222,22 @@ wasi_sock_set_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
11841222
return __WASI_ENOSYS;
11851223
}
11861224

1225+
static wasi_errno_t
1226+
wasi_sock_set_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
1227+
uint64_t timeout_us)
1228+
{
1229+
wasm_module_inst_t module_inst = get_module_inst(exec_env);
1230+
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
1231+
struct fd_table *curfds = NULL;
1232+
1233+
if (!wasi_ctx)
1234+
return __WASI_EACCES;
1235+
1236+
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
1237+
1238+
return wasmtime_ssp_sock_set_recv_timeout(curfds, fd, timeout_us);
1239+
}
1240+
11871241
static wasi_errno_t
11881242
wasi_sock_set_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 reuse)
11891243
{
@@ -1203,6 +1257,22 @@ wasi_sock_set_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
12031257
return __WASI_ENOSYS;
12041258
}
12051259

1260+
static wasi_errno_t
1261+
wasi_sock_set_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
1262+
uint64_t timeout_us)
1263+
{
1264+
wasm_module_inst_t module_inst = get_module_inst(exec_env);
1265+
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
1266+
struct fd_table *curfds = NULL;
1267+
1268+
if (!wasi_ctx)
1269+
return __WASI_EACCES;
1270+
1271+
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
1272+
1273+
return wasmtime_ssp_sock_set_send_timeout(curfds, fd, timeout_us);
1274+
}
1275+
12061276
static wasi_errno_t
12071277
wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data,
12081278
uint32 ri_data_len, wasi_riflags_t ri_flags, uint32 *ro_data_len,
@@ -1427,17 +1497,21 @@ static NativeSymbol native_symbols_libc_wasi[] = {
14271497
REG_NATIVE_FUNC(sock_close, "(i)i"),
14281498
REG_NATIVE_FUNC(sock_connect, "(i*)i"),
14291499
REG_NATIVE_FUNC(sock_get_recv_buf_size, "(i*)i"),
1500+
REG_NATIVE_FUNC(sock_get_recv_timeout, "(i*)i"),
14301501
REG_NATIVE_FUNC(sock_get_reuse_addr, "(i*)i"),
14311502
REG_NATIVE_FUNC(sock_get_reuse_port, "(i*)i"),
14321503
REG_NATIVE_FUNC(sock_get_send_buf_size, "(i*)i"),
1504+
REG_NATIVE_FUNC(sock_get_send_timeout, "(i*)i"),
14331505
REG_NATIVE_FUNC(sock_listen, "(ii)i"),
14341506
REG_NATIVE_FUNC(sock_open, "(iii*)i"),
14351507
REG_NATIVE_FUNC(sock_recv, "(i*ii**)i"),
14361508
REG_NATIVE_FUNC(sock_send, "(i*ii*)i"),
14371509
REG_NATIVE_FUNC(sock_set_recv_buf_size, "(ii)i"),
1510+
REG_NATIVE_FUNC(sock_set_recv_timeout, "(iI)i"),
14381511
REG_NATIVE_FUNC(sock_set_reuse_addr, "(ii)i"),
14391512
REG_NATIVE_FUNC(sock_set_reuse_port, "(ii)i"),
14401513
REG_NATIVE_FUNC(sock_set_send_buf_size, "(ii)i"),
1514+
REG_NATIVE_FUNC(sock_set_send_timeout, "(iI)i"),
14411515
REG_NATIVE_FUNC(sock_shutdown, "(ii)i"),
14421516
REG_NATIVE_FUNC(sched_yield, "()i"),
14431517
};

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,38 @@ __wasi_errno_t wasmtime_ssp_sock_shutdown(
10881088
__wasi_fd_t sock
10891089
) WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) __attribute__((__warn_unused_result__));
10901090

1091+
__wasi_errno_t wasmtime_ssp_sock_set_recv_timeout(
1092+
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
1093+
struct fd_table *curfds,
1094+
#endif
1095+
__wasi_fd_t sock,
1096+
uint64_t timeout_us
1097+
) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_timeout) __attribute__((__warn_unused_result__));
1098+
1099+
__wasi_errno_t wasmtime_ssp_sock_get_recv_timeout(
1100+
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
1101+
struct fd_table *curfds,
1102+
#endif
1103+
__wasi_fd_t sock,
1104+
uint64_t *timeout_us
1105+
) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_timeout) __attribute__((__warn_unused_result__));
1106+
1107+
__wasi_errno_t wasmtime_ssp_sock_set_send_timeout(
1108+
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
1109+
struct fd_table *curfds,
1110+
#endif
1111+
__wasi_fd_t sock,
1112+
uint64_t timeout_us
1113+
) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_timeout) __attribute__((__warn_unused_result__));
1114+
1115+
__wasi_errno_t wasmtime_ssp_sock_get_send_timeout(
1116+
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
1117+
struct fd_table *curfds,
1118+
#endif
1119+
__wasi_fd_t sock,
1120+
uint64_t *timeout_us
1121+
) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_timeout) __attribute__((__warn_unused_result__));
1122+
10911123
__wasi_errno_t wasmtime_ssp_sched_yield(void)
10921124
WASMTIME_SSP_SYSCALL_NAME(sched_yield) __attribute__((__warn_unused_result__));
10931125

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3556,3 +3556,37 @@ addr_pool_destroy(struct addr_pool *addr_pool)
35563556
cur = next;
35573557
}
35583558
}
3559+
3560+
#ifndef WASMTIME_SSP_STATIC_CURFDS
3561+
#define WASMTIME_SSP_PASSTHROUGH_FD_TABLE struct fd_table *curfds,
3562+
#else
3563+
#define WASMTIME_SSP_PASSTHROUGH_FD_TABLE
3564+
#endif
3565+
3566+
// Defines a function that passes through the socket option to the OS
3567+
// implementation
3568+
#define WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(FUNC_NAME, OPTION_TYPE) \
3569+
__wasi_errno_t wasmtime_ssp_sock_##FUNC_NAME( \
3570+
WASMTIME_SSP_PASSTHROUGH_FD_TABLE __wasi_fd_t sock, \
3571+
OPTION_TYPE option) \
3572+
{ \
3573+
struct fd_object *fo; \
3574+
__wasi_errno_t error; \
3575+
int ret; \
3576+
error = fd_object_get(curfds, &fo, sock, 0, 0); \
3577+
if (error != 0) \
3578+
return error; \
3579+
ret = os_socket_##FUNC_NAME(fd_number(fo), option); \
3580+
fd_object_release(fo); \
3581+
if (BHT_OK != ret) \
3582+
return convert_errno(errno); \
3583+
return __WASI_ESUCCESS; \
3584+
}
3585+
3586+
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_send_timeout, uint64)
3587+
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_send_timeout, uint64 *)
3588+
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_recv_timeout, uint64)
3589+
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_recv_timeout, uint64 *)
3590+
3591+
#undef WASMTIME_SSP_PASSTHROUGH_FD_TABLE
3592+
#undef WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION

0 commit comments

Comments
 (0)