mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-07-15 08:48:33 +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