Merge dev/socket into main (#1393)
Implement more socket APIs, refer to #1336 and below PRs: - Implement wasi_addr_resolve function (#1319) - Fix socket-api byte order issue when host/network order are the same (#1327) - Enhance sock_addr_local syscall (#1320) - Implement sock_addr_remote syscall (#1360) - Add support for IPv6 in WAMR (#1411) - Implement ns lookup allowlist (#1420) - Implement sock_send_to and sock_recv_from system calls (#1457) - Added http downloader and multicast socket options (#1467) - Fix `bind()` calls to receive the correct size of `sockaddr` structure (#1490) - Assert on correct parameters (#1505) - Copy only received bytes from socket recv buffer into the app buffer (#1497) Co-authored-by: Marcin Kolny <mkolny@amazon.com> Co-authored-by: Marcin Kolny <marcin.kolny@gmail.com> Co-authored-by: Callum Macmillan <callumimacmillan@gmail.com>
This commit is contained in:
@ -6,6 +6,7 @@
|
||||
#ifndef _WASI_SOCKET_EXT_H_
|
||||
#define _WASI_SOCKET_EXT_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@ -20,7 +21,12 @@ typedef uint16_t __wasi_ip_port_t;
|
||||
|
||||
typedef enum { IPv4 = 0, IPv6 } __wasi_addr_type_t;
|
||||
|
||||
/* n0.n1.n2.n3 */
|
||||
/*
|
||||
n0.n1.n2.n3
|
||||
Example:
|
||||
IP Address: 127.0.0.1
|
||||
Structure: {n0: 127, n1: 0, n2: 0, n3: 1}
|
||||
*/
|
||||
typedef struct __wasi_addr_ip4_t {
|
||||
uint8_t n0;
|
||||
uint8_t n1;
|
||||
@ -30,9 +36,18 @@ typedef struct __wasi_addr_ip4_t {
|
||||
|
||||
typedef struct __wasi_addr_ip4_port_t {
|
||||
__wasi_addr_ip4_t addr;
|
||||
__wasi_ip_port_t port;
|
||||
__wasi_ip_port_t port; /* host byte order */
|
||||
} __wasi_addr_ip4_port_t;
|
||||
|
||||
/*
|
||||
n0:n1:n2:n3:h0:h1:h2:h3, each 16bit value uses host byte order
|
||||
Example (little-endian system)
|
||||
IP Address fe80::3ba2:893b:4be0:e3dd
|
||||
Structure: {
|
||||
n0: 0xfe80, n1:0x0, n2: 0x0, n3: 0x0,
|
||||
h0: 0x3ba2, h1: 0x893b, h2: 0x4be0, h3: 0xe3dd
|
||||
}
|
||||
*/
|
||||
typedef struct __wasi_addr_ip6_t {
|
||||
uint16_t n0;
|
||||
uint16_t n1;
|
||||
@ -46,9 +61,17 @@ typedef struct __wasi_addr_ip6_t {
|
||||
|
||||
typedef struct __wasi_addr_ip6_port_t {
|
||||
__wasi_addr_ip6_t addr;
|
||||
__wasi_ip_port_t port;
|
||||
__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 {
|
||||
@ -59,6 +82,18 @@ typedef struct __wasi_addr_t {
|
||||
|
||||
typedef enum { INET4 = 0, INET6 } __wasi_address_family_t;
|
||||
|
||||
typedef struct __wasi_addr_info_t {
|
||||
__wasi_addr_t addr;
|
||||
__wasi_sock_type_t type;
|
||||
} __wasi_addr_info_t;
|
||||
|
||||
typedef struct __wasi_addr_info_hints_t {
|
||||
__wasi_sock_type_t type;
|
||||
__wasi_address_family_t family;
|
||||
// this is to workaround lack of optional parameters
|
||||
uint8_t hints_enabled;
|
||||
} __wasi_addr_info_hints_t;
|
||||
|
||||
#ifdef __wasi__
|
||||
/**
|
||||
* Reimplement below POSIX APIs with __wasi_sock_XXX functions.
|
||||
@ -67,6 +102,43 @@ typedef enum { INET4 = 0, INET6 } __wasi_address_family_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. */
|
||||
int ai_socktype; /* Socket type. */
|
||||
int ai_protocol; /* Protocol for socket. */
|
||||
socklen_t ai_addrlen; /* Length of socket address. */
|
||||
struct sockaddr *ai_addr; /* Socket address for socket. */
|
||||
char *ai_canonname; /* Canonical name for service location. */
|
||||
struct addrinfo *ai_next; /* Pointer to next in list. */
|
||||
};
|
||||
|
||||
int
|
||||
accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
|
||||
@ -86,8 +158,37 @@ 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);
|
||||
|
||||
int
|
||||
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);
|
||||
|
||||
void
|
||||
freeaddrinfo(struct addrinfo *res);
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -115,16 +216,15 @@ __wasi_sock_accept(__wasi_fd_t fd, __wasi_fd_t *fd_new)
|
||||
* either IP4 or IP6.
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_addr_local(int32_t arg0, int32_t arg1,
|
||||
int32_t arg2)
|
||||
__imported_wasi_snapshot_preview1_sock_addr_local(int32_t arg0, int32_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_addr_local")));
|
||||
|
||||
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(
|
||||
(int32_t)fd, (int32_t)buf, (int32_t)buf_len);
|
||||
(int32_t)fd, (int32_t)addr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -136,43 +236,49 @@ __wasi_sock_addr_local(__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len)
|
||||
* either IP4 or IP6.
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_addr_remote(int32_t arg0, int32_t arg1,
|
||||
int32_t arg2)
|
||||
__imported_wasi_snapshot_preview1_sock_addr_remote(int32_t arg0, int32_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_addr_remote")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_addr_remote(__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len)
|
||||
__wasi_sock_addr_remote(__wasi_fd_t fd, __wasi_addr_t *addr)
|
||||
{
|
||||
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_remote(
|
||||
(int32_t)fd, (int32_t)buf, (int32_t)buf_len);
|
||||
(int32_t)fd, (int32_t)addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a hostname and a port to one or more IP addresses. Port is optional
|
||||
* and you can pass 0 (zero) in most cases, it is used a hint for protocol.
|
||||
* Resolve a hostname and a service to one or more IP addresses. Service is
|
||||
* optional and you can pass empty string in most cases, it is used as a hint
|
||||
* for protocol.
|
||||
*
|
||||
* Note: This is similar to `getaddrinfo` in POSIX
|
||||
*
|
||||
* When successful, the contents of the output buffer consist of a sequence of
|
||||
* IPv4 and/or IPv6 addresses. Each address entry consists of a addr_t object.
|
||||
* IPv4 and/or IPv6 addresses. Each address entry consists of a wasi_addr_t
|
||||
* object.
|
||||
*
|
||||
* This function fills the output buffer as much as possible, potentially
|
||||
* truncating the last address entry. It is advisable that the buffer is
|
||||
* This function fills the output buffer as much as possible, truncating the
|
||||
* entries that didn't fit into the buffer. A number of available addresses
|
||||
* will be returned through the last parameter.
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_addr_resolve(int32_t arg0, int32_t arg1,
|
||||
int32_t arg2, int32_t arg3,
|
||||
int32_t arg4)
|
||||
__imported_wasi_snapshot_preview1_sock_addr_resolve(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__("addr_resolve")));
|
||||
__import_name__("sock_addr_resolve")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_addr_resolve(__wasi_fd_t fd, const char *host, __wasi_ip_port_t port,
|
||||
uint8_t *buf, __wasi_size_t size)
|
||||
__wasi_sock_addr_resolve(const char *host, const char *service,
|
||||
__wasi_addr_info_hints_t *hints,
|
||||
__wasi_addr_info_t *addr_info,
|
||||
__wasi_size_t addr_info_size,
|
||||
__wasi_size_t *max_info_size)
|
||||
{
|
||||
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_addr_resolve(
|
||||
(int32_t)fd, (int32_t)host, (int32_t)port, (int32_t)buf, (int32_t)size);
|
||||
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_resolve(
|
||||
(int32_t)host, (int32_t)service, (int32_t)hints, (int32_t)addr_info,
|
||||
(int32_t)addr_info_size, (int32_t)max_info_size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -191,6 +297,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.
|
||||
@ -252,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,
|
||||
@ -270,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,
|
||||
@ -367,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,
|
||||
@ -385,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,
|
||||
@ -397,20 +545,435 @@ __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
|
||||
__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);
|
||||
}
|
||||
|
||||
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,
|
||||
* we tend to keep original implentations of recv() and send().
|
||||
*/
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -18,16 +18,44 @@
|
||||
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)
|
||||
{
|
||||
out->kind = IPv4;
|
||||
out->addr.ip4.port = ntohs(port);
|
||||
out->addr.ip4.addr.n3 = (addr_num & 0xFF000000) >> 24;
|
||||
out->addr.ip4.addr.n2 = (addr_num & 0x00FF0000) >> 16;
|
||||
out->addr.ip4.addr.n1 = (addr_num & 0x0000FF00) >> 8;
|
||||
out->addr.ip4.addr.n0 = (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
|
||||
ipv6_addr_to_wasi_addr(uint16_t *addr, uint16_t port, __wasi_addr_t *out)
|
||||
{
|
||||
out->kind = IPv6;
|
||||
out->addr.ip6.port = ntohs(port);
|
||||
ipv6_addr_to_wasi_ipv6_addr(addr, &(out->addr.ip6.addr));
|
||||
}
|
||||
|
||||
static __wasi_errno_t
|
||||
@ -36,15 +64,17 @@ sockaddr_to_wasi_addr(const struct sockaddr *sock_addr, socklen_t addrlen,
|
||||
{
|
||||
__wasi_errno_t ret = __WASI_ERRNO_SUCCESS;
|
||||
if (AF_INET == sock_addr->sa_family) {
|
||||
assert(sizeof(struct sockaddr_in) == addrlen);
|
||||
assert(sizeof(struct sockaddr_in) <= addrlen);
|
||||
|
||||
ipv4_addr_to_wasi_addr(
|
||||
((struct sockaddr_in *)sock_addr)->sin_addr.s_addr,
|
||||
((struct sockaddr_in *)sock_addr)->sin_port, wasi_addr);
|
||||
}
|
||||
else if (AF_INET6 == sock_addr->sa_family) {
|
||||
// TODO: IPV6
|
||||
ret = __WASI_ERRNO_AFNOSUPPORT;
|
||||
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);
|
||||
}
|
||||
else {
|
||||
ret = __WASI_ERRNO_AFNOSUPPORT;
|
||||
@ -54,38 +84,52 @@ sockaddr_to_wasi_addr(const struct sockaddr *sock_addr, socklen_t addrlen,
|
||||
}
|
||||
|
||||
static __wasi_errno_t
|
||||
sock_addr_remote(__wasi_fd_t fd, struct sockaddr *sock_addr, socklen_t *addrlen)
|
||||
wasi_addr_to_sockaddr(const __wasi_addr_t *wasi_addr,
|
||||
struct sockaddr *sock_addr, socklen_t *addrlen)
|
||||
{
|
||||
__wasi_addr_t wasi_addr = { 0 };
|
||||
__wasi_errno_t error;
|
||||
switch (wasi_addr->kind) {
|
||||
case IPv4:
|
||||
{
|
||||
struct sockaddr_in sock_addr_in = { 0 };
|
||||
uint32_t s_addr;
|
||||
|
||||
error =
|
||||
__wasi_sock_addr_remote(fd, (uint8_t *)&wasi_addr, sizeof(wasi_addr));
|
||||
if (__WASI_ERRNO_SUCCESS != error) {
|
||||
return error;
|
||||
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:
|
||||
{
|
||||
struct sockaddr_in6 sock_addr_in6 = { 0 };
|
||||
uint16_t *addr_buf = (uint16_t *)sock_addr_in6.sin6_addr.s6_addr;
|
||||
|
||||
addr_buf[0] = htons(wasi_addr->addr.ip6.addr.n0);
|
||||
addr_buf[1] = htons(wasi_addr->addr.ip6.addr.n1);
|
||||
addr_buf[2] = htons(wasi_addr->addr.ip6.addr.n2);
|
||||
addr_buf[3] = htons(wasi_addr->addr.ip6.addr.n3);
|
||||
addr_buf[4] = htons(wasi_addr->addr.ip6.addr.h0);
|
||||
addr_buf[5] = htons(wasi_addr->addr.ip6.addr.h1);
|
||||
addr_buf[6] = htons(wasi_addr->addr.ip6.addr.h2);
|
||||
addr_buf[7] = htons(wasi_addr->addr.ip6.addr.h3);
|
||||
|
||||
sock_addr_in6.sin6_family = AF_INET6;
|
||||
sock_addr_in6.sin6_port = htons(wasi_addr->addr.ip6.port);
|
||||
memcpy(sock_addr, &sock_addr_in6, sizeof(sock_addr_in6));
|
||||
|
||||
*addrlen = sizeof(sock_addr_in6);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return __WASI_ERRNO_AFNOSUPPORT;
|
||||
}
|
||||
|
||||
if (IPv4 == wasi_addr.kind) {
|
||||
struct sockaddr_in sock_addr_in = { 0 };
|
||||
|
||||
sock_addr_in.sin_family = AF_INET;
|
||||
sock_addr_in.sin_addr.s_addr = (wasi_addr.addr.ip4.addr.n3 << 24)
|
||||
| (wasi_addr.addr.ip4.addr.n2 << 16)
|
||||
| (wasi_addr.addr.ip4.addr.n1 << 8)
|
||||
| wasi_addr.addr.ip4.addr.n0;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -99,9 +143,8 @@ accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
||||
error = __wasi_sock_accept(sockfd, &new_sockfd);
|
||||
HANDLE_ERROR(error)
|
||||
|
||||
// error = sock_addr_remote(new_sockfd, addr, addrlen);
|
||||
// HANDLE_ERROR(error)
|
||||
*addrlen = 0;
|
||||
error = getpeername(new_sockfd, addr, addrlen);
|
||||
HANDLE_ERROR(error)
|
||||
|
||||
return new_sockfd;
|
||||
}
|
||||
@ -221,6 +264,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)
|
||||
{
|
||||
@ -256,3 +359,612 @@ socket(int domain, int type, int protocol)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int
|
||||
getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
__wasi_addr_t wasi_addr = { 0 };
|
||||
__wasi_errno_t error;
|
||||
|
||||
error = __wasi_sock_addr_remote(sockfd, &wasi_addr);
|
||||
HANDLE_ERROR(error)
|
||||
|
||||
error = wasi_addr_to_sockaddr(&wasi_addr, addr, addrlen);
|
||||
HANDLE_ERROR(error)
|
||||
|
||||
return __WASI_ERRNO_SUCCESS;
|
||||
}
|
||||
|
||||
struct aibuf {
|
||||
struct addrinfo ai;
|
||||
union sa {
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
} sa;
|
||||
};
|
||||
|
||||
static __wasi_errno_t
|
||||
addrinfo_hints_to_wasi_hints(const struct addrinfo *hints,
|
||||
__wasi_addr_info_hints_t *wasi_hints)
|
||||
{
|
||||
if (hints) {
|
||||
wasi_hints->hints_enabled = 1;
|
||||
|
||||
switch (hints->ai_family) {
|
||||
case AF_INET:
|
||||
wasi_hints->family = INET4;
|
||||
break;
|
||||
case AF_INET6:
|
||||
wasi_hints->family = INET6;
|
||||
break;
|
||||
default:
|
||||
return __WASI_ERRNO_AFNOSUPPORT;
|
||||
}
|
||||
switch (hints->ai_socktype) {
|
||||
case SOCK_STREAM:
|
||||
wasi_hints->type = SOCKET_STREAM;
|
||||
break;
|
||||
case SOCK_DGRAM:
|
||||
wasi_hints->type = SOCKET_DGRAM;
|
||||
break;
|
||||
default:
|
||||
return __WASI_ERRNO_NOTSUP;
|
||||
}
|
||||
|
||||
if (hints->ai_protocol != 0) {
|
||||
return __WASI_ERRNO_NOTSUP;
|
||||
}
|
||||
|
||||
if (hints->ai_flags != 0) {
|
||||
return __WASI_ERRNO_NOTSUP;
|
||||
}
|
||||
}
|
||||
else {
|
||||
wasi_hints->hints_enabled = 0;
|
||||
}
|
||||
|
||||
return __WASI_ERRNO_SUCCESS;
|
||||
}
|
||||
|
||||
static __wasi_errno_t
|
||||
wasi_addr_info_to_addr_info(const __wasi_addr_info_t *addr_info,
|
||||
struct addrinfo *ai)
|
||||
{
|
||||
ai->ai_socktype =
|
||||
addr_info->type == SOCKET_DGRAM ? SOCK_DGRAM : SOCK_STREAM;
|
||||
ai->ai_protocol = 0;
|
||||
ai->ai_canonname = NULL;
|
||||
|
||||
if (addr_info->addr.kind == IPv4) {
|
||||
ai->ai_family = AF_INET;
|
||||
ai->ai_addrlen = sizeof(struct sockaddr_in);
|
||||
}
|
||||
else {
|
||||
ai->ai_family = AF_INET6;
|
||||
ai->ai_addrlen = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
|
||||
return wasi_addr_to_sockaddr(&addr_info->addr, ai->ai_addr,
|
||||
&ai->ai_addrlen); // TODO err handling
|
||||
}
|
||||
|
||||
int
|
||||
getaddrinfo(const char *node, const char *service, const struct addrinfo *hints,
|
||||
struct addrinfo **res)
|
||||
{
|
||||
__wasi_addr_info_hints_t wasi_hints;
|
||||
__wasi_addr_info_t *addr_info = NULL;
|
||||
__wasi_size_t addr_info_size, i;
|
||||
__wasi_size_t max_info_size = 16;
|
||||
__wasi_errno_t error;
|
||||
struct aibuf *aibuf_res;
|
||||
|
||||
error = addrinfo_hints_to_wasi_hints(hints, &wasi_hints);
|
||||
HANDLE_ERROR(error)
|
||||
|
||||
do {
|
||||
if (addr_info)
|
||||
free(addr_info);
|
||||
|
||||
addr_info_size = max_info_size;
|
||||
addr_info = (__wasi_addr_info_t *)malloc(addr_info_size
|
||||
* sizeof(__wasi_addr_info_t));
|
||||
|
||||
if (!addr_info) {
|
||||
HANDLE_ERROR(__WASI_ERRNO_NOMEM)
|
||||
}
|
||||
|
||||
error = __wasi_sock_addr_resolve(node, service == NULL ? "" : service,
|
||||
&wasi_hints, addr_info, addr_info_size,
|
||||
&max_info_size);
|
||||
if (error != __WASI_ERRNO_SUCCESS) {
|
||||
free(addr_info);
|
||||
HANDLE_ERROR(error);
|
||||
}
|
||||
} while (max_info_size > addr_info_size);
|
||||
|
||||
if (addr_info_size == 0) {
|
||||
free(addr_info);
|
||||
*res = NULL;
|
||||
return __WASI_ERRNO_SUCCESS;
|
||||
}
|
||||
|
||||
aibuf_res = calloc(1, addr_info_size * sizeof(struct aibuf));
|
||||
if (!aibuf_res) {
|
||||
free(addr_info);
|
||||
HANDLE_ERROR(__WASI_ERRNO_NOMEM)
|
||||
}
|
||||
|
||||
*res = &aibuf_res[0].ai;
|
||||
|
||||
if (addr_info_size) {
|
||||
addr_info_size = max_info_size;
|
||||
}
|
||||
|
||||
for (i = 0; i < addr_info_size; i++) {
|
||||
struct addrinfo *ai = &aibuf_res[i].ai;
|
||||
ai->ai_addr = (struct sockaddr *)&aibuf_res[i].sa;
|
||||
|
||||
error = wasi_addr_info_to_addr_info(&addr_info[i], ai);
|
||||
if (error != __WASI_ERRNO_SUCCESS) {
|
||||
free(addr_info);
|
||||
free(aibuf_res);
|
||||
HANDLE_ERROR(error)
|
||||
}
|
||||
ai->ai_next = i == addr_info_size - 1 ? NULL : &aibuf_res[i + 1].ai;
|
||||
}
|
||||
|
||||
free(addr_info);
|
||||
|
||||
return __WASI_ERRNO_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
freeaddrinfo(struct addrinfo *res)
|
||||
{
|
||||
/* res is a pointer to a first field in the first element
|
||||
* 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;
|
||||
bool is_linger_enabled;
|
||||
int linger_s;
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user