mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-07-15 16:58:34 +00:00
Import Base Code
This commit is contained in:
parent
b9740beb31
commit
cdaab9f05c
302
core/shared/platform/zephyr/zephyr_errno.h
Normal file
302
core/shared/platform/zephyr/zephyr_errno.h
Normal file
|
@ -0,0 +1,302 @@
|
||||||
|
#ifndef ZEPHYR_ERRNO_H
|
||||||
|
#define ZEPHYR_ERRNO_H
|
||||||
|
|
||||||
|
#include "platform_wasi_types.h"
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
// Add your custom code here
|
||||||
|
static inline __wasi_errno_t
|
||||||
|
zephyr_to_wasi_errno(int zephyr_errno) {
|
||||||
|
switch (zephyr_errno) {
|
||||||
|
case EPERM:
|
||||||
|
return __WASI_EPERM; // Operation not permitted
|
||||||
|
case ENOENT:
|
||||||
|
return __WASI_ENOENT; // No such file or directory
|
||||||
|
case ESRCH:
|
||||||
|
return __WASI_ESRCH; // No such process
|
||||||
|
case EINTR:
|
||||||
|
return __WASI_EINTR; // Interrupted system call
|
||||||
|
case EIO:
|
||||||
|
return __WASI_EIO; // I/O error
|
||||||
|
case ENXIO:
|
||||||
|
return __WASI_ENXIO; // No such device or address
|
||||||
|
case E2BIG:
|
||||||
|
return __WASI_E2BIG; // Argument list too long
|
||||||
|
case ENOEXEC:
|
||||||
|
return __WASI_ENOEXEC; // Exec format error
|
||||||
|
case EBADF:
|
||||||
|
return __WASI_EBADF; // Bad file descriptor
|
||||||
|
case ECHILD:
|
||||||
|
return __WASI_ECHILD; // No child processes
|
||||||
|
case EAGAIN:
|
||||||
|
return __WASI_EAGAIN; // Try again
|
||||||
|
case ENOMEM:
|
||||||
|
return __WASI_ENOMEM; // Out of memory
|
||||||
|
case EACCES:
|
||||||
|
return __WASI_EACCES; // Permission denied
|
||||||
|
case EFAULT:
|
||||||
|
return __WASI_EFAULT; // Bad address
|
||||||
|
case EBUSY:
|
||||||
|
return __WASI_EBUSY; // Device or resource busy
|
||||||
|
case EEXIST:
|
||||||
|
return __WASI_EEXIST; // File exists
|
||||||
|
case EXDEV:
|
||||||
|
return __WASI_EXDEV; // Cross-device link
|
||||||
|
case ENODEV:
|
||||||
|
return __WASI_ENODEV; // No such device
|
||||||
|
case ENOTDIR:
|
||||||
|
return __WASI_ENOTDIR; // Not a directory
|
||||||
|
case EISDIR:
|
||||||
|
return __WASI_EISDIR; // Is a directory
|
||||||
|
case EINVAL:
|
||||||
|
return __WASI_EINVAL; // Invalid argument
|
||||||
|
case ENFILE:
|
||||||
|
return __WASI_ENFILE; // File table overflow
|
||||||
|
case EMFILE:
|
||||||
|
return __WASI_EMFILE; // Too many open files
|
||||||
|
case ENOTTY:
|
||||||
|
return __WASI_ENOTTY; // Not a typewriter
|
||||||
|
case EFBIG:
|
||||||
|
return __WASI_EFBIG; // File too large
|
||||||
|
case ENOSPC:
|
||||||
|
return __WASI_ENOSPC; // No space left on device
|
||||||
|
case EROFS:
|
||||||
|
return __WASI_EROFS; // Read-only file system
|
||||||
|
case EMLINK:
|
||||||
|
return __WASI_EMLINK; // Too many links
|
||||||
|
case EPIPE:
|
||||||
|
return __WASI_EPIPE; // Broken pipe
|
||||||
|
case EDOM:
|
||||||
|
return __WASI_EDOM; // Math argument out of domain of func
|
||||||
|
case ERANGE:
|
||||||
|
return __WASI_ERANGE; // Math result not representable
|
||||||
|
case ENOMSG:
|
||||||
|
return __WASI_ENOMSG; // No message of desired type
|
||||||
|
case EDEADLK:
|
||||||
|
return __WASI_EDEADLK; // Resource deadlock would occur
|
||||||
|
case ENOLCK:
|
||||||
|
return __WASI_ENOLCK; // No record locks available
|
||||||
|
case ENOSYS:
|
||||||
|
return __WASI_ENOSYS; // Function not implemented
|
||||||
|
case ENOTEMPTY:
|
||||||
|
return __WASI_ENOTEMPTY; // Directory not empty
|
||||||
|
case ENAMETOOLONG:
|
||||||
|
return __WASI_ENAMETOOLONG; // File name too long
|
||||||
|
case ELOOP:
|
||||||
|
return __WASI_ELOOP; // Too many symbolic links encountered
|
||||||
|
case EOPNOTSUPP:
|
||||||
|
return __WASI_ENOTSUP; // Operation not supported on transport endpoint
|
||||||
|
case EPFNOSUPPORT:
|
||||||
|
return __WASI_EAFNOSUPPORT; // Protocol family not supported
|
||||||
|
case ECONNRESET:
|
||||||
|
return __WASI_ECONNRESET; // Connection reset by peer
|
||||||
|
case ENOBUFS:
|
||||||
|
return __WASI_ENOBUFS; // No buffer space available
|
||||||
|
case EAFNOSUPPORT:
|
||||||
|
return __WASI_EAFNOSUPPORT; // Address family not supported by protocol
|
||||||
|
case EPROTOTYPE:
|
||||||
|
return __WASI_EPROTOTYPE; // Protocol wrong type for socket
|
||||||
|
case ENOTSOCK:
|
||||||
|
return __WASI_ENOTSOCK; // Socket operation on non-socket
|
||||||
|
case ENOPROTOOPT:
|
||||||
|
return __WASI_ENOPROTOOPT; // Protocol not available
|
||||||
|
case ESHUTDOWN:
|
||||||
|
return __WASI_ECANCELED; // Cannot send after transport endpoint shutdown
|
||||||
|
case ECONNREFUSED:
|
||||||
|
return __WASI_ECONNREFUSED; // Connection refused
|
||||||
|
case EADDRINUSE:
|
||||||
|
return __WASI_EADDRINUSE; // Address already in use
|
||||||
|
case ECONNABORTED:
|
||||||
|
return __WASI_ECONNABORTED; // Connection aborted
|
||||||
|
case ENETUNREACH:
|
||||||
|
return __WASI_ENETUNREACH; // Network is unreachable
|
||||||
|
case ENETDOWN:
|
||||||
|
return __WASI_ENETDOWN; // Network is down
|
||||||
|
case ETIMEDOUT:
|
||||||
|
return __WASI_ETIMEDOUT; // Connection timed out
|
||||||
|
case EHOSTDOWN:
|
||||||
|
return __WASI_ENETDOWN; // Host is down
|
||||||
|
case EHOSTUNREACH:
|
||||||
|
return __WASI_EHOSTUNREACH; // No route to host
|
||||||
|
case EINPROGRESS:
|
||||||
|
return __WASI_EINPROGRESS; // Operation now in progress
|
||||||
|
case EALREADY:
|
||||||
|
return __WASI_EALREADY; // Operation already in progress
|
||||||
|
case EDESTADDRREQ:
|
||||||
|
return __WASI_EDESTADDRREQ; // Destination address required
|
||||||
|
case EMSGSIZE:
|
||||||
|
return __WASI_EMSGSIZE; // Message too long
|
||||||
|
case EPROTONOSUPPORT:
|
||||||
|
return __WASI_EPROTONOSUPPORT; // Protocol not supported
|
||||||
|
case ESOCKTNOSUPPORT:
|
||||||
|
// return __WASI_ESOCKTNOSUPPORT; // Socket type not supported
|
||||||
|
case EADDRNOTAVAIL:
|
||||||
|
return __WASI_EADDRNOTAVAIL; // Cannot assign requested address
|
||||||
|
case ENETRESET:
|
||||||
|
return __WASI_ENETRESET; // Network dropped connection because of reset
|
||||||
|
case EISCONN:
|
||||||
|
return __WASI_EISCONN; // Transport endpoint is already connected
|
||||||
|
case ENOTCONN:
|
||||||
|
return __WASI_ENOTCONN; // Transport endpoint is not connected
|
||||||
|
case ETOOMANYREFS:
|
||||||
|
return __WASI_ENOTRECOVERABLE; // Too many references: cannot splice
|
||||||
|
case ENOTSUP:
|
||||||
|
return __WASI_ENOTSUP; // Operation not supported
|
||||||
|
case EILSEQ:
|
||||||
|
return __WASI_EILSEQ; // Illegal byte sequence
|
||||||
|
case EOVERFLOW:
|
||||||
|
return __WASI_EOVERFLOW; // Value too large for defined data type
|
||||||
|
case ECANCELED:
|
||||||
|
return __WASI_ECANCELED; // Operation canceled
|
||||||
|
default:
|
||||||
|
return __WASI_ENOSYS; // Function not implemented
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
wasi_to_zephyr_errno(__wasi_errno_t wasi_errno) {
|
||||||
|
switch (wasi_errno) {
|
||||||
|
case __WASI_EPERM:
|
||||||
|
return EPERM;
|
||||||
|
case __WASI_ENOENT:
|
||||||
|
return ENOENT;
|
||||||
|
case __WASI_ESRCH:
|
||||||
|
return ESRCH;
|
||||||
|
case __WASI_EINTR:
|
||||||
|
return EINTR;
|
||||||
|
case __WASI_EIO:
|
||||||
|
return EIO;
|
||||||
|
case __WASI_ENXIO:
|
||||||
|
return ENXIO;
|
||||||
|
case __WASI_E2BIG:
|
||||||
|
return E2BIG;
|
||||||
|
case __WASI_ENOEXEC:
|
||||||
|
return ENOEXEC;
|
||||||
|
case __WASI_EBADF:
|
||||||
|
return EBADF;
|
||||||
|
case __WASI_ECHILD:
|
||||||
|
return ECHILD;
|
||||||
|
case __WASI_EAGAIN:
|
||||||
|
return EAGAIN;
|
||||||
|
case __WASI_ENOMEM:
|
||||||
|
return ENOMEM;
|
||||||
|
case __WASI_EACCES:
|
||||||
|
return EACCES;
|
||||||
|
case __WASI_EFAULT:
|
||||||
|
return EFAULT;
|
||||||
|
case __WASI_EBUSY:
|
||||||
|
return EBUSY;
|
||||||
|
case __WASI_EEXIST:
|
||||||
|
return EEXIST;
|
||||||
|
case __WASI_EXDEV:
|
||||||
|
return EXDEV;
|
||||||
|
case __WASI_ENODEV:
|
||||||
|
return ENODEV;
|
||||||
|
case __WASI_ENOTDIR:
|
||||||
|
return ENOTDIR;
|
||||||
|
case __WASI_EISDIR:
|
||||||
|
return EISDIR;
|
||||||
|
case __WASI_EINVAL:
|
||||||
|
return EINVAL;
|
||||||
|
case __WASI_ENFILE:
|
||||||
|
return ENFILE;
|
||||||
|
case __WASI_EMFILE:
|
||||||
|
return EMFILE;
|
||||||
|
case __WASI_ENOTTY:
|
||||||
|
return ENOTTY;
|
||||||
|
case __WASI_EFBIG:
|
||||||
|
return EFBIG;
|
||||||
|
case __WASI_ENOSPC:
|
||||||
|
return ENOSPC;
|
||||||
|
case __WASI_EROFS:
|
||||||
|
return EROFS;
|
||||||
|
case __WASI_EMLINK:
|
||||||
|
return EMLINK;
|
||||||
|
case __WASI_EPIPE:
|
||||||
|
return EPIPE;
|
||||||
|
case __WASI_EDOM:
|
||||||
|
return EDOM;
|
||||||
|
case __WASI_ERANGE:
|
||||||
|
return ERANGE;
|
||||||
|
case __WASI_ENOMSG:
|
||||||
|
return ENOMSG;
|
||||||
|
case __WASI_EDEADLK:
|
||||||
|
return EDEADLK;
|
||||||
|
case __WASI_ENOLCK:
|
||||||
|
return ENOLCK;
|
||||||
|
case __WASI_ENOSYS:
|
||||||
|
return ENOSYS;
|
||||||
|
case __WASI_ENOTEMPTY:
|
||||||
|
return ENOTEMPTY;
|
||||||
|
case __WASI_ENAMETOOLONG:
|
||||||
|
return ENAMETOOLONG;
|
||||||
|
case __WASI_ELOOP:
|
||||||
|
return ELOOP;
|
||||||
|
//case __WASI_ENOTSUPP :
|
||||||
|
// return EOPNOTSUPP;
|
||||||
|
case __WASI_EAFNOSUPPORT:
|
||||||
|
return EPFNOSUPPORT;
|
||||||
|
case __WASI_ECONNRESET:
|
||||||
|
return ECONNRESET;
|
||||||
|
case __WASI_ENOBUFS:
|
||||||
|
return ENOBUFS;
|
||||||
|
case __WASI_EPROTOTYPE:
|
||||||
|
return EPROTOTYPE;
|
||||||
|
case __WASI_ENOTSOCK:
|
||||||
|
return ENOTSOCK;
|
||||||
|
case __WASI_ENOPROTOOPT:
|
||||||
|
return ENOPROTOOPT;
|
||||||
|
//case __WASI_ECANCELED:
|
||||||
|
// return ESHUTDOWN;
|
||||||
|
case __WASI_ECONNREFUSED:
|
||||||
|
return ECONNREFUSED;
|
||||||
|
case __WASI_EADDRINUSE:
|
||||||
|
return EADDRINUSE;
|
||||||
|
case __WASI_ECONNABORTED:
|
||||||
|
return ECONNABORTED;
|
||||||
|
case __WASI_ENETUNREACH:
|
||||||
|
return ENETUNREACH;
|
||||||
|
case __WASI_ENETDOWN:
|
||||||
|
return ENETDOWN;
|
||||||
|
case __WASI_ETIMEDOUT:
|
||||||
|
return ETIMEDOUT;
|
||||||
|
// case __WASI_EHOSTDOWN:
|
||||||
|
// return EHOSTDOWN;
|
||||||
|
case __WASI_EHOSTUNREACH:
|
||||||
|
return EHOSTUNREACH;
|
||||||
|
case __WASI_EINPROGRESS:
|
||||||
|
return EINPROGRESS;
|
||||||
|
case __WASI_EALREADY:
|
||||||
|
return EALREADY;
|
||||||
|
case __WASI_EDESTADDRREQ:
|
||||||
|
return EDESTADDRREQ;
|
||||||
|
case __WASI_EMSGSIZE:
|
||||||
|
return EMSGSIZE;
|
||||||
|
case __WASI_EPROTONOSUPPORT:
|
||||||
|
return EPROTONOSUPPORT;
|
||||||
|
// case __WASI_ESOCKTNOSUPPORT:
|
||||||
|
// return ESOCKTNOSUPPORT;
|
||||||
|
case __WASI_EADDRNOTAVAIL:
|
||||||
|
return EADDRNOTAVAIL;
|
||||||
|
case __WASI_ENETRESET:
|
||||||
|
return ENETRESET;
|
||||||
|
case __WASI_EISCONN:
|
||||||
|
return EISCONN;
|
||||||
|
case __WASI_ENOTCONN:
|
||||||
|
return ENOTCONN;
|
||||||
|
case __WASI_ENOTRECOVERABLE:
|
||||||
|
return ETOOMANYREFS;
|
||||||
|
case __WASI_ENOTSUP:
|
||||||
|
return ENOTSUP;
|
||||||
|
case __WASI_EILSEQ:
|
||||||
|
return EILSEQ;
|
||||||
|
case __WASI_EOVERFLOW:
|
||||||
|
return EOVERFLOW;
|
||||||
|
case __WASI_ECANCELED:
|
||||||
|
return ECANCELED;
|
||||||
|
default:
|
||||||
|
return ENOSYS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* ZEPHYR_ERRNO_H */
|
992
core/shared/platform/zephyr/zephyr_socket.c
Normal file
992
core/shared/platform/zephyr/zephyr_socket.c
Normal file
|
@ -0,0 +1,992 @@
|
||||||
|
#include "platform_api_extension.h"
|
||||||
|
//#include "platform_wasi_types.h"
|
||||||
|
|
||||||
|
#include <zephyr/net/net_ip.h>
|
||||||
|
#include <zephyr/net/socket.h>
|
||||||
|
#include <zephyr/net/socket_types.h>
|
||||||
|
#include "zephyr_errno.h"
|
||||||
|
|
||||||
|
// Static functions
|
||||||
|
static bool
|
||||||
|
textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr *out,
|
||||||
|
socklen_t *out_len)
|
||||||
|
{
|
||||||
|
struct sockaddr_in *v4;
|
||||||
|
#ifdef IPPROTO_IPV6
|
||||||
|
struct sockaddr_in *v6;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
assert(textual);
|
||||||
|
|
||||||
|
v4 = (struct sockaddr_in *)out;
|
||||||
|
if (inet_pton(AF_INET, textual, &v4->sin_addr.s_addr) == 1) {
|
||||||
|
v4->sin_family = AF_INET;
|
||||||
|
v4->sin_port = htons(port);
|
||||||
|
*out_len = sizeof(struct sockaddr_in);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef IPPROTO_IPV6
|
||||||
|
v6 = (struct sockaddr_in *)out;
|
||||||
|
if (inet_pton(AF_INET6, textual, &v6->sin6_addr.s6_addr) == 1) {
|
||||||
|
v6->sin6_family = AF_INET6;
|
||||||
|
v6->sin6_port = htons(port);
|
||||||
|
*out_len = sizeof(struct sockaddr_in);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr,
|
||||||
|
bh_sockaddr_t *bh_sockaddr)
|
||||||
|
{
|
||||||
|
switch (sockaddr->sa_family) {
|
||||||
|
case AF_INET:
|
||||||
|
{
|
||||||
|
struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
|
||||||
|
|
||||||
|
bh_sockaddr->port = ntohs(addr->sin_port);
|
||||||
|
bh_sockaddr->addr_buffer.ipv4 = ntohl(addr->sin_addr.s_addr);
|
||||||
|
bh_sockaddr->is_ipv4 = true;
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
#ifdef IPPROTO_IPV6
|
||||||
|
case AF_INET6:
|
||||||
|
{
|
||||||
|
struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
bh_sockaddr->port = ntohs(addr->sin6_port);
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(bh_sockaddr->addr_buffer.ipv6)
|
||||||
|
/ sizeof(bh_sockaddr->addr_buffer.ipv6[0]);
|
||||||
|
i++) {
|
||||||
|
uint16 part_addr = addr->sin6_addr.s6_addr[i * 2]
|
||||||
|
| (addr->sin6_addr.s6_addr[i * 2 + 1] << 8);
|
||||||
|
bh_sockaddr->addr_buffer.ipv6[i] = ntohs(part_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bh_sockaddr->is_ipv4 = false;
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
errno = EAFNOSUPPORT;
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bh_sockaddr_to_sockaddr(const bh_sockaddr_t *bh_sockaddr,
|
||||||
|
struct sockaddr_storage *sockaddr, socklen_t *socklen)
|
||||||
|
{
|
||||||
|
if (bh_sockaddr->is_ipv4) {
|
||||||
|
struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
|
||||||
|
addr->sin_port = htons(bh_sockaddr->port);
|
||||||
|
addr->sin_family = AF_INET;
|
||||||
|
addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_buffer.ipv4);
|
||||||
|
*socklen = sizeof(*addr);
|
||||||
|
}
|
||||||
|
#ifdef IPPROTO_IPV6
|
||||||
|
else {
|
||||||
|
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)sockaddr;
|
||||||
|
size_t i;
|
||||||
|
addr->sin6_port = htons(bh_sockaddr->port);
|
||||||
|
addr->sin6_family = AF_INET6;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(bh_sockaddr->addr_buffer.ipv6)
|
||||||
|
/ sizeof(bh_sockaddr->addr_buffer.ipv6[0]);
|
||||||
|
i++) {
|
||||||
|
uint16 part_addr = htons(bh_sockaddr->addr_buffer.ipv6[i]);
|
||||||
|
addr->sin6_addr.s6_addr[i * 2] = 0xff & part_addr;
|
||||||
|
addr->sin6_addr.s6_addr[i * 2 + 1] = (0xff00 & part_addr) >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
*socklen = sizeof(*addr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
getaddrinfo_error_to_errno(int error)
|
||||||
|
{
|
||||||
|
switch (error) {
|
||||||
|
case EAI_AGAIN:
|
||||||
|
return EAGAIN;
|
||||||
|
case EAI_FAIL:
|
||||||
|
return EFAULT;
|
||||||
|
case EAI_MEMORY:
|
||||||
|
return ENOMEM;
|
||||||
|
case EAI_SYSTEM:
|
||||||
|
return errno;
|
||||||
|
default:
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
is_addrinfo_supported(struct addrinfo *info)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
// Allow only IPv4 and IPv6
|
||||||
|
(info->ai_family == AF_INET || info->ai_family == AF_INET6)
|
||||||
|
// Allow only UDP and TCP
|
||||||
|
&& (info->ai_socktype == SOCK_DGRAM || info->ai_socktype == SOCK_STREAM)
|
||||||
|
&& (info->ai_protocol == IPPROTO_TCP
|
||||||
|
|| info->ai_protocol == IPPROTO_UDP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
os_socket_setbooloption(bh_socket_t socket, int level, int optname,
|
||||||
|
bool is_enabled)
|
||||||
|
{
|
||||||
|
int option = (int)is_enabled;
|
||||||
|
|
||||||
|
if (zsock_setsockopt(socket, level, optname, &option, sizeof(option)) != 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
os_socket_getbooloption(bh_socket_t socket, int level, int optname,
|
||||||
|
bool *is_enabled)
|
||||||
|
{
|
||||||
|
assert(is_enabled);
|
||||||
|
|
||||||
|
int optval;
|
||||||
|
socklen_t optval_size = sizeof(optval);
|
||||||
|
|
||||||
|
if (zsock_setsockopt(socket, level, optname, &optval, &optval_size) != 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
*is_enabled = (bool)optval;
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Platform API implementation
|
||||||
|
int
|
||||||
|
os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp)
|
||||||
|
{
|
||||||
|
int af = is_ipv4 ? AF_INET : AF_INET6;
|
||||||
|
|
||||||
|
if (!sock) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_tcp) {
|
||||||
|
*sock = zsock_socket(af, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*sock = zsock_socket(af, SOCK_DGRAM, IPPROTO_UDP); // IPPROTO_UDP or 0 ?
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*sock == -1) ? BHT_ERROR : BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_bind(bh_socket_t socket, const char *host, int *port)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage addr = { 0 };
|
||||||
|
socklen_t socklen;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
assert(host);
|
||||||
|
assert(port);
|
||||||
|
|
||||||
|
if (!textual_addr_to_sockaddr(host, *port, (struct sockaddr *)&addr,
|
||||||
|
&socklen)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
// F_SETF_SETFD and FD_CLOEXEC are not defined in zephyr.
|
||||||
|
// SO_LINGER: Socket lingers on close (ignored, for compatibility)
|
||||||
|
|
||||||
|
ret = zsock_bind(socket, (struct sockaddr *)&addr, socklen);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
socklen = sizeof(addr);
|
||||||
|
if (zsock_getsockname(socket, (void *)&addr, &socklen) == -1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr.sin_family == AF_INET) {
|
||||||
|
*port = ntohs((&addr)->sin_port);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#ifdef IPPROTO_IPV6
|
||||||
|
*port = ntohs((&addr)->sin6_port);
|
||||||
|
#else
|
||||||
|
goto fail;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
// Close the fd because FD_CLOEXEC isn't implemented.
|
||||||
|
os_socket_close(socket);
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_settimeout(bh_socket_t socket, uint64 timeout_us)
|
||||||
|
{
|
||||||
|
struct timeval timeout = { 0 };
|
||||||
|
|
||||||
|
timeout.tv_sec = timeout_us / 1000000;
|
||||||
|
timeout.tv_usec = timeout_us % 1000000;
|
||||||
|
|
||||||
|
return zsock_setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &timeout,
|
||||||
|
sizeof(timeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_listen(bh_socket_t socket, int max_client)
|
||||||
|
{
|
||||||
|
return zsock_listen(socket, max_client) != 0 ? BHT_ERROR : BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
|
||||||
|
unsigned int *addrlen)
|
||||||
|
{
|
||||||
|
*sock = zsock_accept(server_sock, addr, addrlen);
|
||||||
|
|
||||||
|
if (*sock < 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_connect(bh_socket_t socket, const char *addr, int port)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage addr = { 0 };
|
||||||
|
socklen_t socklen;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
assert(addr);
|
||||||
|
|
||||||
|
if (!textual_addr_to_sockaddr(addr, port, (struct sockaddr *)&addr,
|
||||||
|
&socklen)) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = zsock_connect(socket, (struct sockaddr *)&addr, socklen);
|
||||||
|
if (ret < 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
|
||||||
|
{
|
||||||
|
return zsock_recv(socket, buf, len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
|
||||||
|
bh_sockaddr_t *src_addr)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage addr = { 0 };
|
||||||
|
socklen_t socklen = sizeof(addr);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = zsock_recvfrom(socket, buf, len, flags, (struct sockaddr *)&addr,
|
||||||
|
&socklen);
|
||||||
|
if (ret < 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src_addr && socklen > 0) {
|
||||||
|
if (sockaddr_to_bh_sockaddr((struct sockaddr *)&addr, src_addr) != BHT_OK) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
|
||||||
|
{
|
||||||
|
return zsock_send(socket, buf, len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
|
||||||
|
int flags, const bh_sockaddr_t *dest_addr)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage addr = { 0 };
|
||||||
|
socklen_t socklen;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (bh_sockaddr_to_sockaddr(dest_addr, (struct sockaddr *)&addr, &socklen)
|
||||||
|
== BHT_ERROR) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return zsock_sendto(socket, buf, len, flags, (struct sockaddr *)&addr,
|
||||||
|
socklen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_close(bh_socket_t socket)
|
||||||
|
{
|
||||||
|
return zsock_close(socket) == -1 ? BHT_ERROR : BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
__wasi_errno_t
|
||||||
|
os_socket_shutdown(bh_socket_t socket)
|
||||||
|
{
|
||||||
|
if (zsock_shutdown(socket, ZSOCK_SHUT_RDWR) == -1) {
|
||||||
|
return zephyr_to_wasi_errno(errno);
|
||||||
|
}
|
||||||
|
return __WASI_ESUCCESS;;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out)
|
||||||
|
{
|
||||||
|
if (!cp)
|
||||||
|
return BHT_ERROR;
|
||||||
|
|
||||||
|
if (is_ipv4) {
|
||||||
|
if (zsock_inet_pton(AF_INET, cp, &out->ipv4) != 1) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
/* Note: ntohl(INADDR_NONE) == INADDR_NONE */
|
||||||
|
out->ipv4 = ntohl(out->ipv4);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#ifdef IPPROTO_IPV6
|
||||||
|
if (zsock_inet_pton(AF_INET6, cp, out->ipv6) != 1) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
out->ipv6[i] = ntohs(out->ipv6[i]);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
errno = EAFNOSUPPORT;
|
||||||
|
return BHT_ERROR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_addr_resolve(const char *host, const char *service,
|
||||||
|
uint8_t *hint_is_tcp, uint8_t *hint_is_ipv4,
|
||||||
|
bh_addr_info_t *addr_info, size_t addr_info_size,
|
||||||
|
size_t *max_info_size)
|
||||||
|
{
|
||||||
|
struct zsock_addrinfo hints = { 0 }, *res, *result;
|
||||||
|
int hints_enabled = hint_is_tcp || hint_is_ipv4;
|
||||||
|
int ret;
|
||||||
|
size_t pos = 0;
|
||||||
|
|
||||||
|
if (hints_enabled) {
|
||||||
|
if (hint_is_ipv4) {
|
||||||
|
hints.ai_family = *hint_is_ipv4 ? AF_INET : AF_INET6;
|
||||||
|
}
|
||||||
|
if (hint_is_tcp) {
|
||||||
|
hints.ai_socktype = *hint_is_tcp ? SOCK_STREAM : SOCK_DGRAM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = zsock_getaddrinfo(host, strlen(service) == 0 ? NULL : service,
|
||||||
|
hints_enabled ? &hints : NULL, &result);
|
||||||
|
if (ret != BHT_OK) {
|
||||||
|
errno = getaddrinfo_error_to_errno(ret);
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = result;
|
||||||
|
|
||||||
|
while (res) {
|
||||||
|
if (addr_info_size > pos) {
|
||||||
|
if (!is_addrinfo_supported(res)) {
|
||||||
|
res = res->ai_next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret =
|
||||||
|
sockaddr_to_bh_sockaddr(res->ai_addr, &addr_info[pos].sockaddr);
|
||||||
|
|
||||||
|
if (ret == BHT_ERROR) {
|
||||||
|
zsock_freeaddrinfo(result);
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr_info[pos].is_tcp = res->ai_socktype == SOCK_STREAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos++;
|
||||||
|
res = res->ai_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
*max_info_size = pos;
|
||||||
|
zsock_freeaddrinfo(result);
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage addr_storage = { 0 };
|
||||||
|
socklen_t addr_len = sizeof(addr_storage);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = zsock_getsockname(socket, (struct sockaddr *)&addr_storage, &addr_len);
|
||||||
|
|
||||||
|
if (ret != BHT_OK) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr_storage, sockaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage addr_storage = { 0 };
|
||||||
|
socklen_t addr_len = sizeof(addr_storage);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = zsock_getpeername(socket, (struct sockaddr *)&addr_storage, &addr_len);
|
||||||
|
|
||||||
|
if (ret != BHT_OK) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr_storage, sockaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz)
|
||||||
|
{
|
||||||
|
int buf_size_int = (int)bufsiz;
|
||||||
|
|
||||||
|
if (zsock_setsockopt(socket, SOL_SOCKET, SO_SNDBUF, &buf_size_int,
|
||||||
|
sizeof(buf_size_int))
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz)
|
||||||
|
{
|
||||||
|
assert(bufsiz);
|
||||||
|
|
||||||
|
int buf_size_int;
|
||||||
|
socklen_t bufsiz_len = sizeof(buf_size_int);
|
||||||
|
|
||||||
|
if (zsock_getsockopt(socket, SOL_SOCKET, SO_SNDBUF, &buf_size_int,
|
||||||
|
&bufsiz_len)
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*bufsiz = (size_t)buf_size_int;
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz)
|
||||||
|
{
|
||||||
|
int buf_size_int = (int)bufsiz;
|
||||||
|
|
||||||
|
if (zsock_getsockopt(socket, SOL_SOCKET, SO_RCVBUF, &buf_size_int,
|
||||||
|
sizeof(buf_size_int))
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz)
|
||||||
|
{
|
||||||
|
assert(bufsiz);
|
||||||
|
|
||||||
|
int buf_size_int;
|
||||||
|
socklen_t bufsiz_len = sizeof(buf_size_int);
|
||||||
|
|
||||||
|
if (zsock_getsockopt(socket, SOL_SOCKET, SO_RCVBUF, &buf_size_int, &bufsiz_len)
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
*bufsiz = (size_t)buf_size_int;
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled)
|
||||||
|
{
|
||||||
|
return os_socket_setbooloption(socket, SOL_SOCKET, SO_KEEPALIVE,
|
||||||
|
is_enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled)
|
||||||
|
{
|
||||||
|
return os_socket_getbooloption(socket, SOL_SOCKET, SO_KEEPALIVE,
|
||||||
|
is_enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = timeout_us / 1000000UL;
|
||||||
|
tv.tv_usec = timeout_us % 1000000UL;
|
||||||
|
|
||||||
|
if (zsock_setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) != 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
socklen_t tv_len = sizeof(tv);
|
||||||
|
|
||||||
|
if (zsock_setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, &tv_len) != 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
*timeout_us = (tv.tv_sec * 1000000UL) + tv.tv_usec;
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = timeout_us / 1000000UL;
|
||||||
|
tv.tv_usec = timeout_us % 1000000UL;
|
||||||
|
|
||||||
|
if (zsock_setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) != 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
socklen_t tv_len = sizeof(tv);
|
||||||
|
|
||||||
|
if (zsock_setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, &tv_len) != 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
*timeout_us = (tv.tv_sec * 1000000UL) + tv.tv_usec;
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled)
|
||||||
|
{
|
||||||
|
return os_socket_setbooloption(socket, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
is_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled)
|
||||||
|
{
|
||||||
|
return os_socket_getbooloption(socket, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
is_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled)
|
||||||
|
{
|
||||||
|
return os_socket_setbooloption(socket, SOL_SOCKET, SO_REUSEPORT,
|
||||||
|
is_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled)
|
||||||
|
{
|
||||||
|
return os_socket_getbooloption(socket, SOL_SOCKET, SO_REUSEPORT,
|
||||||
|
is_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SO_LINGER Socket lingers on close (ignored, for compatibility)
|
||||||
|
int
|
||||||
|
os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TCP_NODELAY Disable TCP buffering (ignored, for compatibility)
|
||||||
|
int
|
||||||
|
os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32_t time_s)
|
||||||
|
{
|
||||||
|
int time_s_int = (int)time_s;
|
||||||
|
|
||||||
|
#ifdef TCP_KEEPIDLE
|
||||||
|
if (zsock_setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &time_s_int,
|
||||||
|
sizeof(time_s_int))
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
return BHT_OK;
|
||||||
|
#elif defined(TCP_KEEPALIVE)
|
||||||
|
if (zsock_setsockopt(socket, IPPROTO_TCP, TCP_KEEPALIVE, &time_s_int,
|
||||||
|
sizeof(time_s_int))
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
return BHT_OK;
|
||||||
|
#else
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32_t *time_s)
|
||||||
|
{
|
||||||
|
assert(time_s);
|
||||||
|
int time_s_int;
|
||||||
|
socklen_t time_s_len = sizeof(time_s_int);
|
||||||
|
|
||||||
|
#ifdef TCP_KEEPIDLE
|
||||||
|
if (getsozsock_setsockoptkopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &time_s_int, &time_s_len)
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
*time_s = (uint32)time_s_int;
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
#elif defined(TCP_KEEPALIVE)
|
||||||
|
if (zsock_setsockopt(socket, IPPROTO_TCP, TCP_KEEPALIVE, &time_s_int, &time_s_len)
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
*time_s = (uint32)time_s_int;
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
#else
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32_t time_s)
|
||||||
|
{
|
||||||
|
int time_s_int = (int)time_s;
|
||||||
|
|
||||||
|
#ifdef TCP_KEEPINTVL
|
||||||
|
if (zsock_setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &time_s_int,
|
||||||
|
sizeof(time_s_int))
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
#else
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32_t *time_s)
|
||||||
|
{
|
||||||
|
#ifdef TCP_KEEPINTVL
|
||||||
|
assert(time_s);
|
||||||
|
int time_s_int;
|
||||||
|
socklen_t time_s_len = sizeof(time_s_int);
|
||||||
|
|
||||||
|
if (zsock_setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &time_s_int, &time_s_len)
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
*time_s = (uint32)time_s_int;
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
#else
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6,
|
||||||
|
bool *is_enabled)
|
||||||
|
{
|
||||||
|
errno = ENOSYS;
|
||||||
|
|
||||||
|
return BHT_ERROR;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_ip_add_membership(bh_socket_t socket,
|
||||||
|
bh_ip_addr_buffer_t *imr_multiaddr,
|
||||||
|
uint32_t imr_interface, bool is_ipv6)
|
||||||
|
{
|
||||||
|
assert(imr_multiaddr);
|
||||||
|
|
||||||
|
if(is_ipv6){
|
||||||
|
#if defined(IPPROTO_IPV6) && !defined(BH_PLATFORM_COSMOPOLITAN)
|
||||||
|
struct ipv6_mreq mreq;
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
((uint16_t *)mreq.ipv6mr_multiaddr.s6_addr)[i] =
|
||||||
|
imr_multiaddr->ipv6[i];
|
||||||
|
}
|
||||||
|
mreq.ipv6mr_interface = imr_interface;
|
||||||
|
|
||||||
|
if (setsockopt(socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq,
|
||||||
|
sizeof(mreq))
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
errno = EAFNOSUPPORT;
|
||||||
|
return BHT_ERROR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
struct ip_mreq mreq;
|
||||||
|
mreq.imr_multiaddr.s_addr = imr_multiaddr->ipv4;
|
||||||
|
mreq.imr_interface.s_addr = imr_interface;
|
||||||
|
|
||||||
|
if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
|
||||||
|
sizeof(mreq))
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_ip_drop_membership(bh_socket_t socket,
|
||||||
|
bh_ip_addr_buffer_t *imr_multiaddr,
|
||||||
|
uint32_t imr_interface, bool is_ipv6)
|
||||||
|
{
|
||||||
|
assert(imr_multiaddr);
|
||||||
|
|
||||||
|
if(is_ipv6){
|
||||||
|
#if defined(IPPROTO_IPV6) && !defined(BH_PLATFORM_COSMOPOLITAN)
|
||||||
|
struct ipv6_mreq mreq;
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
((uint16_t *)mreq.ipv6mr_multiaddr.s6_addr)[i] =
|
||||||
|
imr_multiaddr->ipv6[i];
|
||||||
|
}
|
||||||
|
mreq.ipv6mr_interface = imr_interface;
|
||||||
|
|
||||||
|
if (setsockopt(socket, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq,
|
||||||
|
sizeof(mreq))
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
errno = EAFNOSUPPORT;
|
||||||
|
return BHT_ERROR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
struct ip_mreq mreq;
|
||||||
|
mreq.imr_multiaddr.s_addr = imr_multiaddr->ipv4;
|
||||||
|
mreq.imr_interface.s_addr = imr_interface;
|
||||||
|
|
||||||
|
if (setsockopt(socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq,
|
||||||
|
sizeof(mreq))
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s)
|
||||||
|
{
|
||||||
|
if (zsock_setsockopt(socket, IPPROTO_IP, IP_TTL, &ttl_s, sizeof(ttl_s)) != 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s)
|
||||||
|
{
|
||||||
|
socklen_t opt_len = sizeof(*ttl_s);
|
||||||
|
|
||||||
|
if (zsock_setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, ttl_s, &opt_len)
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s)
|
||||||
|
{
|
||||||
|
if (zsock_setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl_s, sizeof(ttl_s)) != 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s)
|
||||||
|
{
|
||||||
|
socklen_t opt_len = sizeof(*ttl_s);
|
||||||
|
|
||||||
|
if (zsock_setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, ttl_s, &opt_len)
|
||||||
|
!= 0) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_ipv6_only(bh_socket_t socket, bool is_enabled)
|
||||||
|
{
|
||||||
|
#ifdef IPPROTO_IPV6
|
||||||
|
return os_socket_setbooloption(socket, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||||
|
is_enabled);
|
||||||
|
#else
|
||||||
|
errno = EAFNOSUPPORT;
|
||||||
|
return BHT_ERROR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_ipv6_only(bh_socket_t socket, bool *is_enabled)
|
||||||
|
{
|
||||||
|
#ifdef IPPROTO_IPV6
|
||||||
|
return os_socket_getbooloption(socket, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||||
|
is_enabled);
|
||||||
|
#else
|
||||||
|
errno = EAFNOSUPPORT;
|
||||||
|
return BHT_ERROR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_set_broadcast(bh_socket_t socket, bool is_enabled)
|
||||||
|
{
|
||||||
|
return os_socket_setbooloption(socket, SOL_SOCKET, SO_BROADCAST,
|
||||||
|
is_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled)
|
||||||
|
{
|
||||||
|
return os_socket_getbooloption(socket, SOL_SOCKET, SO_BROADCAST,
|
||||||
|
is_enabled);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user