Added http downloader and multicast socket options (#1467)

Add a group of socket options used by cURL and rust stdlib, as well as some UDP multicast options.
This commit is contained in:
Callum Macmillan
2022-09-15 10:09:39 +01:00
committed by GitHub
parent b731ca4668
commit 4de5b52ba0
12 changed files with 3493 additions and 64 deletions

View File

@ -6,6 +6,7 @@
#ifndef _WASI_SOCKET_EXT_H_
#define _WASI_SOCKET_EXT_H_
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@ -63,6 +64,14 @@ typedef struct __wasi_addr_ip6_port_t {
__wasi_ip_port_t port; /* host byte order */
} __wasi_addr_ip6_port_t;
typedef struct __wasi_addr_ip_t {
__wasi_addr_type_t kind;
union {
__wasi_addr_ip4_t ip4;
__wasi_addr_ip6_t ip6;
} addr;
} __wasi_addr_ip_t;
typedef struct __wasi_addr_t {
__wasi_addr_type_t kind;
union {
@ -93,10 +102,33 @@ typedef struct __wasi_addr_info_hints_t {
* <sys/socket.h>
* <sys/types.h>
*/
#define SO_REUSEADDR 2
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
#define SO_KEEPALIVE 9
#define SO_LINGER 13
#define SO_REUSEPORT 15
#define SO_RCVTIMEO 20
#define SO_SNDTIMEO 21
#define TCP_NODELAY 1
#define TCP_KEEPIDLE 4
#define TCP_KEEPINTVL 5
#define TCP_QUICKACK 12
#define TCP_FASTOPEN_CONNECT 30
#define IP_TTL 2
#define IP_MULTICAST_TTL 33
#define IP_MULTICAST_LOOP 34
#define IP_ADD_MEMBERSHIP 35
#define IP_DROP_MEMBERSHIP 36
#define IPV6_MULTICAST_LOOP 19
#define IPV6_JOIN_GROUP 20
#define IPV6_LEAVE_GROUP 21
#define IPV6_V6ONLY 26
struct addrinfo {
int ai_flags; /* Input flags. */
int ai_family; /* Protocol family for socket. */
@ -368,7 +400,7 @@ __imported_wasi_snapshot_preview1_sock_get_reuse_addr(int32_t arg0,
__import_name__("sock_get_reuse_addr")));
static inline __wasi_errno_t
__wasi_sock_get_reuse_addr(__wasi_fd_t fd, uint8_t *reuse)
__wasi_sock_get_reuse_addr(__wasi_fd_t fd, bool *reuse)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_reuse_addr((int32_t)fd,
@ -386,7 +418,7 @@ __imported_wasi_snapshot_preview1_sock_get_reuse_port(int32_t arg0,
__import_name__("sock_get_reuse_port")));
static inline __wasi_errno_t
__wasi_sock_get_reuse_port(__wasi_fd_t fd, int8_t *reuse)
__wasi_sock_get_reuse_port(__wasi_fd_t fd, bool *reuse)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_reuse_port((int32_t)fd,
@ -483,7 +515,7 @@ __imported_wasi_snapshot_preview1_sock_set_reuse_addr(int32_t arg0,
__import_name__("sock_set_reuse_addr")));
static inline __wasi_errno_t
__wasi_sock_set_reuse_addr(__wasi_fd_t fd, uint8_t reuse)
__wasi_sock_set_reuse_addr(__wasi_fd_t fd, bool reuse)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_reuse_addr((int32_t)fd,
@ -501,7 +533,7 @@ __imported_wasi_snapshot_preview1_sock_set_reuse_port(int32_t arg0,
__import_name__("sock_set_reuse_port")));
static inline __wasi_errno_t
__wasi_sock_set_reuse_port(__wasi_fd_t fd, uint8_t reuse)
__wasi_sock_set_reuse_port(__wasi_fd_t fd, bool reuse)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_reuse_port((int32_t)fd,
@ -513,15 +545,17 @@ __wasi_sock_set_reuse_port(__wasi_fd_t fd, uint8_t reuse)
* Note: This is similar to `setsockopt` in POSIX for SO_SNDBUF
*/
int32_t
__imported_wasi_snapshot_preview1_sock_set_send_buf_size(int32_t arg0)
__imported_wasi_snapshot_preview1_sock_set_send_buf_size(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_send_buf_size")));
static inline __wasi_errno_t
__wasi_sock_set_send_buf_size(__wasi_fd_t fd)
__wasi_sock_set_send_buf_size(__wasi_fd_t fd, __wasi_size_t buf_len)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_send_buf_size((int32_t)fd);
__imported_wasi_snapshot_preview1_sock_set_send_buf_size(
(int32_t)fd, (int32_t)buf_len);
}
int32_t
@ -580,6 +614,363 @@ __wasi_sock_set_send_timeout(__wasi_fd_t fd, uint64_t timeout_us)
(int32_t)fd, (int64_t)timeout_us);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_keep_alive(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_keep_alive")));
static inline __wasi_errno_t
__wasi_sock_set_keep_alive(__wasi_fd_t fd, bool option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_keep_alive((int32_t)fd,
(int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_keep_alive(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_keep_alive")));
static inline __wasi_errno_t
__wasi_sock_get_keep_alive(__wasi_fd_t fd, bool *option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_keep_alive((int32_t)fd,
(int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_linger(int32_t arg0, int32_t arg1,
int32_t arg2)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_linger")));
static inline __wasi_errno_t
__wasi_sock_set_linger(__wasi_fd_t fd, bool is_enabled, int linger_s)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_linger(
(int32_t)fd, (int32_t)is_enabled, (int32_t)linger_s);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_linger(int32_t arg0, int32_t arg1,
int32_t arg2)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_linger")));
static inline __wasi_errno_t
__wasi_sock_get_linger(__wasi_fd_t fd, bool *is_enabled, int *linger_s)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_linger(
(int32_t)fd, (int32_t)is_enabled, (int32_t)linger_s);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_tcp_keep_idle(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_tcp_keep_idle")));
static inline __wasi_errno_t
__wasi_sock_set_tcp_keep_idle(__wasi_fd_t fd, uint32_t time_s)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_tcp_keep_idle(
(int32_t)fd, (int32_t)time_s);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_tcp_keep_idle(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_tcp_keep_idle")));
static inline __wasi_errno_t
__wasi_sock_get_tcp_keep_idle(__wasi_fd_t fd, uint32_t *time_s)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_tcp_keep_idle(
(int32_t)fd, (int32_t)time_s);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_tcp_keep_intvl(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_tcp_keep_intvl")));
static inline __wasi_errno_t
__wasi_sock_set_tcp_keep_intvl(__wasi_fd_t fd, uint32_t time_s)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_tcp_keep_intvl(
(int32_t)fd, (int32_t)time_s);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_tcp_keep_intvl(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_tcp_keep_intvl")));
static inline __wasi_errno_t
__wasi_sock_get_tcp_keep_intvl(__wasi_fd_t fd, uint32_t *time_s)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_tcp_keep_intvl(
(int32_t)fd, (int32_t)time_s);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_tcp_fastopen_connect(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_tcp_fastopen_connect")));
static inline __wasi_errno_t
__wasi_sock_set_tcp_fastopen_connect(__wasi_fd_t fd, bool option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_tcp_fastopen_connect(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_tcp_fastopen_connect(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_tcp_fastopen_connect")));
static inline __wasi_errno_t
__wasi_sock_get_tcp_fastopen_connect(__wasi_fd_t fd, bool *option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_tcp_fastopen_connect(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_ip_multicast_loop(int32_t arg0,
int32_t arg1,
int32_t arg2)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_ip_multicast_loop")));
static inline __wasi_errno_t
__wasi_sock_set_ip_multicast_loop(__wasi_fd_t fd, bool ipv6, bool option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_ip_multicast_loop(
(int32_t)fd, (int32_t)ipv6, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_ip_multicast_loop(int32_t arg0,
int32_t arg1,
int32_t arg2)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_ip_multicast_loop")));
static inline __wasi_errno_t
__wasi_sock_get_ip_multicast_loop(__wasi_fd_t fd, bool ipv6, bool *option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_ip_multicast_loop(
(int32_t)fd, (int32_t)ipv6, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_ip_multicast_ttl(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_ip_multicast_ttl")));
static inline __wasi_errno_t
__wasi_sock_set_ip_multicast_ttl(__wasi_fd_t fd, uint8_t option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_ip_multicast_ttl(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_ip_multicast_ttl(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_ip_multicast_ttl")));
static inline __wasi_errno_t
__wasi_sock_get_ip_multicast_ttl(__wasi_fd_t fd, uint8_t *option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_ip_multicast_ttl(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_ip_add_membership(int32_t arg0,
int32_t arg1,
int32_t arg2)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_ip_add_membership")));
static inline __wasi_errno_t
__wasi_sock_set_ip_add_membership(__wasi_fd_t fd,
__wasi_addr_ip_t *imr_multiaddr,
uint32_t imr_interface)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_ip_add_membership(
(int32_t)fd, (int32_t)imr_multiaddr, (int32_t)imr_interface);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_ip_drop_membership(int32_t arg0,
int32_t arg1,
int32_t arg2)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_ip_drop_membership")));
static inline __wasi_errno_t
__wasi_sock_set_ip_drop_membership(__wasi_fd_t fd,
__wasi_addr_ip_t *imr_multiaddr,
uint32_t imr_interface)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_ip_drop_membership(
(int32_t)fd, (int32_t)imr_multiaddr, (int32_t)imr_interface);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_broadcast(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_broadcast")));
static inline __wasi_errno_t
__wasi_sock_set_broadcast(__wasi_fd_t fd, bool option)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_broadcast(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_broadcast(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_broadcast")));
static inline __wasi_errno_t
__wasi_sock_get_broadcast(__wasi_fd_t fd, bool *option)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_broadcast(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_tcp_no_delay(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_tcp_no_delay")));
static inline __wasi_errno_t
__wasi_sock_set_tcp_no_delay(__wasi_fd_t fd, bool option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_tcp_no_delay(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_tcp_no_delay(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_tcp_no_delay")));
static inline __wasi_errno_t
__wasi_sock_get_tcp_no_delay(__wasi_fd_t fd, bool *option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_tcp_no_delay(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_tcp_quick_ack(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_tcp_quick_ack")));
static inline __wasi_errno_t
__wasi_sock_set_tcp_quick_ack(__wasi_fd_t fd, bool option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_tcp_quick_ack(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_tcp_quick_ack(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_tcp_quick_ack")));
static inline __wasi_errno_t
__wasi_sock_get_tcp_quick_ack(__wasi_fd_t fd, bool *option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_tcp_quick_ack(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_ip_ttl(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_ip_ttl")));
static inline __wasi_errno_t
__wasi_sock_set_ip_ttl(__wasi_fd_t fd, uint8_t option)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_ip_ttl(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_ip_ttl(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_ip_ttl")));
static inline __wasi_errno_t
__wasi_sock_get_ip_ttl(__wasi_fd_t fd, uint8_t *option)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_ip_ttl(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_ipv6_only(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_ipv6_only")));
static inline __wasi_errno_t
__wasi_sock_set_ipv6_only(__wasi_fd_t fd, bool option)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_ipv6_only(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_ipv6_only(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_ipv6_only")));
static inline __wasi_errno_t
__wasi_sock_get_ipv6_only(__wasi_fd_t fd, bool *option)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_ipv6_only(
(int32_t)fd, (int32_t)option);
}
/**
* TODO: modify recv() and send()
* since don't want to re-compile the wasi-libc,

View File

@ -18,17 +18,36 @@
return -1; \
}
static void
ipv4_addr_to_wasi_ip4_addr(uint32_t addr_num, __wasi_addr_ip4_t *out)
{
addr_num = ntohl(addr_num);
out->n0 = (addr_num & 0xFF000000) >> 24;
out->n1 = (addr_num & 0x00FF0000) >> 16;
out->n2 = (addr_num & 0x0000FF00) >> 8;
out->n3 = (addr_num & 0x000000FF);
}
/* addr_num and port are in network order */
static void
ipv4_addr_to_wasi_addr(uint32_t addr_num, uint16_t port, __wasi_addr_t *out)
{
addr_num = ntohl(addr_num);
out->kind = IPv4;
out->addr.ip4.port = ntohs(port);
out->addr.ip4.addr.n0 = (addr_num & 0xFF000000) >> 24;
out->addr.ip4.addr.n1 = (addr_num & 0x00FF0000) >> 16;
out->addr.ip4.addr.n2 = (addr_num & 0x0000FF00) >> 8;
out->addr.ip4.addr.n3 = (addr_num & 0x000000FF);
ipv4_addr_to_wasi_ip4_addr(addr_num, &(out->addr.ip4.addr));
}
static void
ipv6_addr_to_wasi_ipv6_addr(uint16_t *addr, __wasi_addr_ip6_t *out)
{
out->n0 = ntohs(addr[0]);
out->n1 = ntohs(addr[1]);
out->n2 = ntohs(addr[2]);
out->n3 = ntohs(addr[3]);
out->h0 = ntohs(addr[4]);
out->h1 = ntohs(addr[5]);
out->h2 = ntohs(addr[6]);
out->h3 = ntohs(addr[7]);
}
static void
@ -36,14 +55,7 @@ ipv6_addr_to_wasi_addr(uint16_t *addr, uint16_t port, __wasi_addr_t *out)
{
out->kind = IPv6;
out->addr.ip6.port = ntohs(port);
out->addr.ip6.addr.n0 = ntohs(addr[0]);
out->addr.ip6.addr.n1 = ntohs(addr[1]);
out->addr.ip6.addr.n2 = ntohs(addr[2]);
out->addr.ip6.addr.n3 = ntohs(addr[3]);
out->addr.ip6.addr.h0 = ntohs(addr[4]);
out->addr.ip6.addr.h1 = ntohs(addr[5]);
out->addr.ip6.addr.h2 = ntohs(addr[6]);
out->addr.ip6.addr.h3 = ntohs(addr[7]);
ipv6_addr_to_wasi_ipv6_addr(addr, &(out->addr.ip6.addr));
}
static __wasi_errno_t
@ -552,6 +564,8 @@ get_sol_socket_option(int sockfd, int optname, void *__restrict optval,
{
__wasi_errno_t error;
uint64_t timeout_us;
bool is_linger_enabled;
int linger_s;
switch (optname) {
case SO_RCVTIMEO:
@ -566,21 +580,165 @@ get_sol_socket_option(int sockfd, int optname, void *__restrict optval,
HANDLE_ERROR(error);
*(struct timeval *)optval = time_us_to_timeval(timeout_us);
return error;
case SO_SNDBUF:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_send_buf_size(sockfd, (size_t *)optval);
HANDLE_ERROR(error);
return error;
case SO_RCVBUF:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_recv_buf_size(sockfd, (size_t *)optval);
HANDLE_ERROR(error);
return error;
case SO_KEEPALIVE:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_keep_alive(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
case SO_REUSEADDR:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_reuse_addr(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
case SO_REUSEPORT:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_reuse_port(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
case SO_LINGER:
assert(*optlen == sizeof(struct linger));
error =
__wasi_sock_get_linger(sockfd, &is_linger_enabled, &linger_s);
HANDLE_ERROR(error);
((struct linger *)optval)->l_onoff = (int)is_linger_enabled;
((struct linger *)optval)->l_linger = linger_s;
return error;
case SO_BROADCAST:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_broadcast(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
HANDLE_ERROR(__WASI_ERRNO_NOTSUP);
int
get_ipproto_tcp_option(int sockfd, int optname, void *__restrict optval,
socklen_t *__restrict optlen)
{
__wasi_errno_t error;
switch (optname) {
case TCP_KEEPIDLE:
assert(*optlen == sizeof(uint32_t));
error = __wasi_sock_get_tcp_keep_idle(sockfd, (uint32_t *)optval);
HANDLE_ERROR(error);
return error;
case TCP_KEEPINTVL:
assert(*optlen == sizeof(uint32_t));
error = __wasi_sock_get_tcp_keep_intvl(sockfd, (uint32_t *)optval);
HANDLE_ERROR(error);
return error;
case TCP_FASTOPEN_CONNECT:
assert(*optlen == sizeof(int));
error =
__wasi_sock_get_tcp_fastopen_connect(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
case TCP_NODELAY:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_tcp_no_delay(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
case TCP_QUICKACK:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_tcp_quick_ack(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
int
get_ipproto_ip_option(int sockfd, int optname, void *__restrict optval,
socklen_t *__restrict optlen)
{
__wasi_errno_t error;
switch (optname) {
case IP_MULTICAST_LOOP:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_ip_multicast_loop(sockfd, false,
(bool *)optval);
HANDLE_ERROR(error);
return error;
case IP_TTL:
assert(*optlen == sizeof(uint8_t));
error = __wasi_sock_get_ip_ttl(sockfd, (uint8_t *)optval);
HANDLE_ERROR(error);
return error;
case IP_MULTICAST_TTL:
assert(*optlen == sizeof(uint8_t));
error = __wasi_sock_get_ip_multicast_ttl(sockfd, (uint8_t *)optval);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
int
get_ipproto_ipv6_option(int sockfd, int optname, void *__restrict optval,
socklen_t *__restrict optlen)
{
__wasi_errno_t error;
switch (optname) {
case IPV6_V6ONLY:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_ipv6_only(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
case IPV6_MULTICAST_LOOP:
assert(*optlen == sizeof(int));
error =
__wasi_sock_get_ip_multicast_loop(sockfd, true, (bool *)optval);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
int
getsockopt(int sockfd, int level, int optname, void *__restrict optval,
socklen_t *__restrict optlen)
{
__wasi_errno_t error;
switch (level) {
case SOL_SOCKET:
return get_sol_socket_option(sockfd, optname, optval, optlen);
case IPPROTO_TCP:
return get_ipproto_tcp_option(sockfd, optname, optval, optlen);
case IPPROTO_IP:
return get_ipproto_ip_option(sockfd, optname, optval, optlen);
case IPPROTO_IPV6:
return get_ipproto_ipv6_option(sockfd, optname, optval, optlen);
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
HANDLE_ERROR(__WASI_ERRNO_NOTSUP);
}
int
@ -603,19 +761,210 @@ set_sol_socket_option(int sockfd, int optname, const void *optval,
error = __wasi_sock_set_send_timeout(sockfd, timeout_us);
HANDLE_ERROR(error);
return error;
case SO_SNDBUF:
assert(optlen == sizeof(int));
error = __wasi_sock_set_send_buf_size(sockfd, *(size_t *)optval);
HANDLE_ERROR(error);
return error;
case SO_RCVBUF:
assert(optlen == sizeof(int));
error = __wasi_sock_set_recv_buf_size(sockfd, *(size_t *)optval);
HANDLE_ERROR(error);
return error;
case SO_KEEPALIVE:
assert(optlen == sizeof(int));
error = __wasi_sock_set_keep_alive(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
case SO_REUSEADDR:
assert(optlen == sizeof(int));
error = __wasi_sock_set_reuse_addr(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
case SO_REUSEPORT:
assert(optlen == sizeof(int));
error = __wasi_sock_set_reuse_port(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
case SO_LINGER:
assert(optlen == sizeof(struct linger));
struct linger *linger_opt = ((struct linger *)optval);
error = __wasi_sock_set_linger(sockfd, (bool)linger_opt->l_onoff,
linger_opt->l_linger);
HANDLE_ERROR(error);
return error;
case SO_BROADCAST:
assert(optlen == sizeof(int));
error = __wasi_sock_set_broadcast(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
HANDLE_ERROR(__WASI_ERRNO_NOTSUP);
int
set_ipproto_tcp_option(int sockfd, int optname, const void *optval,
socklen_t optlen)
{
__wasi_errno_t error;
switch (optname) {
case TCP_NODELAY:
assert(optlen == sizeof(int));
error = __wasi_sock_set_tcp_no_delay(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
case TCP_KEEPIDLE:
assert(optlen == sizeof(uint32_t));
error = __wasi_sock_set_tcp_keep_idle(sockfd, *(uint32_t *)optval);
HANDLE_ERROR(error);
return error;
case TCP_KEEPINTVL:
assert(optlen == sizeof(uint32_t));
error = __wasi_sock_set_tcp_keep_intvl(sockfd, *(uint32_t *)optval);
HANDLE_ERROR(error);
return error;
case TCP_FASTOPEN_CONNECT:
assert(optlen == sizeof(int));
error =
__wasi_sock_set_tcp_fastopen_connect(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
case TCP_QUICKACK:
assert(optlen == sizeof(int));
error = __wasi_sock_set_tcp_quick_ack(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
int
set_ipproto_ip_option(int sockfd, int optname, const void *optval,
socklen_t optlen)
{
__wasi_errno_t error;
__wasi_addr_ip_t imr_multiaddr;
struct ip_mreq *ip_mreq_opt;
switch (optname) {
case IP_MULTICAST_LOOP:
assert(optlen == sizeof(int));
error = __wasi_sock_set_ip_multicast_loop(sockfd, false,
*(bool *)optval);
HANDLE_ERROR(error);
return error;
case IP_ADD_MEMBERSHIP:
assert(optlen == sizeof(struct ip_mreq));
ip_mreq_opt = (struct ip_mreq *)optval;
imr_multiaddr.kind = IPv4;
ipv4_addr_to_wasi_ip4_addr(ip_mreq_opt->imr_multiaddr.s_addr,
&imr_multiaddr.addr.ip4);
error = __wasi_sock_set_ip_add_membership(
sockfd, &imr_multiaddr, ip_mreq_opt->imr_interface.s_addr);
HANDLE_ERROR(error);
return error;
case IP_DROP_MEMBERSHIP:
assert(optlen == sizeof(struct ip_mreq));
ip_mreq_opt = (struct ip_mreq *)optval;
imr_multiaddr.kind = IPv4;
ipv4_addr_to_wasi_ip4_addr(ip_mreq_opt->imr_multiaddr.s_addr,
&imr_multiaddr.addr.ip4);
error = __wasi_sock_set_ip_drop_membership(
sockfd, &imr_multiaddr, ip_mreq_opt->imr_interface.s_addr);
HANDLE_ERROR(error);
return error;
case IP_TTL:
assert(optlen == sizeof(uint8_t));
error = __wasi_sock_set_ip_ttl(sockfd, *(uint8_t *)optval);
HANDLE_ERROR(error);
return error;
case IP_MULTICAST_TTL:
assert(optlen == sizeof(uint8_t));
error =
__wasi_sock_set_ip_multicast_ttl(sockfd, *(uint8_t *)optval);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
int
set_ipproto_ipv6_option(int sockfd, int optname, const void *optval,
socklen_t optlen)
{
__wasi_errno_t error;
struct ipv6_mreq *ipv6_mreq_opt;
__wasi_addr_ip_t imr_multiaddr;
switch (optname) {
case IPV6_V6ONLY:
assert(optlen == sizeof(int));
error = __wasi_sock_set_ipv6_only(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
case IPV6_MULTICAST_LOOP:
assert(optlen == sizeof(int));
error = __wasi_sock_set_ip_multicast_loop(sockfd, true,
*(bool *)optval);
HANDLE_ERROR(error);
return error;
case IPV6_JOIN_GROUP:
assert(optlen == sizeof(struct ipv6_mreq));
ipv6_mreq_opt = (struct ipv6_mreq *)optval;
imr_multiaddr.kind = IPv6;
ipv6_addr_to_wasi_ipv6_addr(
(uint16_t *)ipv6_mreq_opt->ipv6mr_multiaddr.s6_addr,
&imr_multiaddr.addr.ip6);
error = __wasi_sock_set_ip_add_membership(
sockfd, &imr_multiaddr, ipv6_mreq_opt->ipv6mr_interface);
HANDLE_ERROR(error);
return error;
case IPV6_LEAVE_GROUP:
assert(optlen == sizeof(struct ipv6_mreq));
ipv6_mreq_opt = (struct ipv6_mreq *)optval;
imr_multiaddr.kind = IPv6;
ipv6_addr_to_wasi_ipv6_addr(
(uint16_t *)ipv6_mreq_opt->ipv6mr_multiaddr.s6_addr,
&imr_multiaddr.addr.ip6);
error = __wasi_sock_set_ip_drop_membership(
sockfd, &imr_multiaddr, ipv6_mreq_opt->ipv6mr_interface);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
int
setsockopt(int sockfd, int level, int optname, const void *optval,
socklen_t optlen)
{
__wasi_errno_t error;
switch (level) {
case SOL_SOCKET:
return set_sol_socket_option(sockfd, optname, optval, optlen);
case IPPROTO_TCP:
return set_ipproto_tcp_option(sockfd, optname, optval, optlen);
case IPPROTO_IP:
return set_ipproto_ip_option(sockfd, optname, optval, optlen);
case IPPROTO_IPV6:
return set_ipproto_ipv6_option(sockfd, optname, optval, optlen);
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
HANDLE_ERROR(__WASI_ERRNO_NOTSUP);
}