Implement part of Berkeley Socket API for libc-wasi (#1036)
Refer to [Networking API design](https://github.com/WebAssembly/WASI/issues/370) and [feat(socket): berkeley socket API v2](https://github.com/WebAssembly/WASI/pull/459): - Support the socket API of synchronous mode, including `socket/bind/listen/accept/send/recv/close/shutdown`, the asynchronous mode isn't supported yet. - Support adding `--addr-pool=<pool1,pool2,..>` argument for command line to identify the valid ip address range - Add socket-api sample and update the document
This commit is contained in:
410
core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h
Normal file
410
core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h
Normal file
@ -0,0 +1,410 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _WASI_SOCKET_EXT_H_
|
||||
#define _WASI_SOCKET_EXT_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*Be a part of <wasi/api.h>*/
|
||||
|
||||
typedef enum {
|
||||
SOCKET_DGRAM = 0,
|
||||
SOCKET_STREAM,
|
||||
} __wasi_sock_type_t;
|
||||
|
||||
typedef uint16_t __wasi_ip_port_t;
|
||||
|
||||
typedef enum { IPv4 = 0, IPv6 } __wasi_addr_type_t;
|
||||
|
||||
/* n0.n1.n2.n3 */
|
||||
typedef struct __wasi_addr_ip4_t {
|
||||
uint8_t n0;
|
||||
uint8_t n1;
|
||||
uint8_t n2;
|
||||
uint8_t n3;
|
||||
} __wasi_addr_ip4_t;
|
||||
|
||||
typedef struct __wasi_addr_ip4_port_t {
|
||||
__wasi_addr_ip4_t addr;
|
||||
__wasi_ip_port_t port;
|
||||
} __wasi_addr_ip4_port_t;
|
||||
|
||||
typedef struct __wasi_addr_ip6_t {
|
||||
uint16_t n0;
|
||||
uint16_t n1;
|
||||
uint16_t n2;
|
||||
uint16_t n3;
|
||||
uint16_t h0;
|
||||
uint16_t h1;
|
||||
uint16_t h2;
|
||||
uint16_t h3;
|
||||
} __wasi_addr_ip6_t;
|
||||
|
||||
typedef struct __wasi_addr_ip6_port_t {
|
||||
__wasi_addr_ip6_t addr;
|
||||
__wasi_ip_port_t port;
|
||||
} __wasi_addr_ip6_port_t;
|
||||
|
||||
typedef struct __wasi_addr_t {
|
||||
__wasi_addr_type_t kind;
|
||||
union {
|
||||
__wasi_addr_ip4_port_t ip4;
|
||||
__wasi_addr_ip6_port_t ip6;
|
||||
} addr;
|
||||
} __wasi_addr_t;
|
||||
|
||||
typedef enum { INET4 = 0, INET6 } __wasi_address_family_t;
|
||||
|
||||
#ifdef __wasi__
|
||||
/**
|
||||
* Reimplement below POSIX APIs with __wasi_sock_XXX functions.
|
||||
*
|
||||
* Keep sync with
|
||||
* <sys/socket.h>
|
||||
* <sys/types.h>
|
||||
*/
|
||||
|
||||
int
|
||||
accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
|
||||
|
||||
int
|
||||
bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
int
|
||||
connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
int
|
||||
listen(int sockfd, int backlog);
|
||||
|
||||
int
|
||||
socket(int domain, int type, int protocol);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Accept a connection on a socket
|
||||
* Note: This is similar to `accept`
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_accept(int32_t arg0, int32_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_accept")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_accept(__wasi_fd_t fd, __wasi_fd_t *fd_new)
|
||||
{
|
||||
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_accept(
|
||||
(int32_t)fd, (int32_t)fd_new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the local address to which the socket is bound.
|
||||
*
|
||||
* Note: This is similar to `getsockname` in POSIX
|
||||
*
|
||||
* When successful, the contents of the output buffer consist of an IP address,
|
||||
* either IP4 or IP6.
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_addr_local(int32_t arg0, int32_t arg1,
|
||||
int32_t arg2)
|
||||
__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)
|
||||
{
|
||||
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_local(
|
||||
(int32_t)fd, (int32_t)buf, (int32_t)buf_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remote address to which the socket is connected to.
|
||||
*
|
||||
* Note: This is similar to `getpeername` in POSIX
|
||||
*
|
||||
* When successful, the contents of the output buffer consist of an IP address,
|
||||
* either IP4 or IP6.
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_addr_remote(int32_t arg0, int32_t arg1,
|
||||
int32_t arg2)
|
||||
__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)
|
||||
{
|
||||
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_remote(
|
||||
(int32_t)fd, (int32_t)buf, (int32_t)buf_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This function fills the output buffer as much as possible, potentially
|
||||
* truncating the last address entry. It is advisable that the buffer is
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_addr_resolve(int32_t arg0, int32_t arg1,
|
||||
int32_t arg2, int32_t arg3,
|
||||
int32_t arg4)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind a socket
|
||||
* Note: This is similar to `bind` in POSIX using PF_INET
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_bind(int32_t arg0, int32_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_bind")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_bind(__wasi_fd_t fd, __wasi_addr_t *addr)
|
||||
{
|
||||
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_bind(
|
||||
(int32_t)fd, (int32_t)addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a socket (this is an alias for `fd_close`)
|
||||
* Note: This is similar to `close` in POSIX.
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_close(int32_t arg0)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_close")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_close(__wasi_fd_t fd)
|
||||
{
|
||||
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_close(
|
||||
(int32_t)fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate a connection on a socket to the specified address
|
||||
* Note: This is similar to `connect` in POSIX
|
||||
*/
|
||||
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_connect(int32_t arg0, int32_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_connect")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_connect(__wasi_fd_t fd, __wasi_addr_t *addr)
|
||||
{
|
||||
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_connect(
|
||||
(int32_t)fd, (int32_t)addr);
|
||||
}
|
||||
/**
|
||||
* Retrieve the size of the receive buffer
|
||||
* Note: This is similar to `getsockopt` in POSIX for SO_RCVBUF
|
||||
*/
|
||||
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_get_recv_buf_size(int32_t arg0,
|
||||
int32_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_get_recv_buf_size")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_get_recv_buf_size(__wasi_fd_t fd, __wasi_size_t *size)
|
||||
{
|
||||
return (__wasi_errno_t)
|
||||
__imported_wasi_snapshot_preview1_sock_get_recv_buf_size((int32_t)fd,
|
||||
(int32_t)size);
|
||||
}
|
||||
/**
|
||||
* Retrieve status of address reuse on a socket
|
||||
* Note: This is similar to `getsockopt` in POSIX for SO_REUSEADDR
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_get_reuse_addr(int32_t arg0,
|
||||
int32_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_get_reuse_addr")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_get_reuse_addr(__wasi_fd_t fd, uint8_t *reuse)
|
||||
{
|
||||
return (__wasi_errno_t)
|
||||
__imported_wasi_snapshot_preview1_sock_get_reuse_addr((int32_t)fd,
|
||||
(int32_t)reuse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve status of port reuse on a socket
|
||||
* Note: This is similar to `getsockopt` in POSIX for SO_REUSEPORT
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_get_reuse_port(int32_t arg0,
|
||||
int32_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_get_reuse_port")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_get_reuse_port(__wasi_fd_t fd, int8_t *reuse)
|
||||
{
|
||||
return (__wasi_errno_t)
|
||||
__imported_wasi_snapshot_preview1_sock_get_reuse_port((int32_t)fd,
|
||||
(int32_t)reuse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the size of the send buffer
|
||||
* Note: This is similar to `getsockopt` in POSIX for SO_SNDBUF
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_get_send_buf_size(int32_t arg0,
|
||||
int32_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_get_send_buf_size")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_get_send_buf_size(__wasi_fd_t fd, __wasi_size_t *size)
|
||||
{
|
||||
return (__wasi_errno_t)
|
||||
__imported_wasi_snapshot_preview1_sock_get_send_buf_size((int32_t)fd,
|
||||
(int32_t)size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen for connections on a socket
|
||||
* Note: This is similar to `listen`
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_listen(int32_t arg0, int32_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_listen")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_listen(__wasi_fd_t fd, __wasi_size_t backlog)
|
||||
{
|
||||
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_listen(
|
||||
(int32_t)fd, (int32_t)backlog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a socket
|
||||
|
||||
* The first argument to this function is a handle to an
|
||||
* address pool. The address pool determines what actions can
|
||||
* be performed and at which addresses they can be performed to.
|
||||
|
||||
* The address pool cannot be re-assigned. You will need to close
|
||||
* the socket and open a new one to use a different address pool.
|
||||
|
||||
* Note: This is similar to `socket` in POSIX using PF_INET
|
||||
*/
|
||||
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_open(int32_t arg0, int32_t arg1,
|
||||
int32_t arg2, int32_t arg3)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_open")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_open(__wasi_fd_t fd, __wasi_address_family_t af,
|
||||
__wasi_sock_type_t socktype, __wasi_fd_t *sockfd)
|
||||
{
|
||||
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_open(
|
||||
(int32_t)fd, (int32_t)af, (int32_t)socktype, (int32_t)sockfd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set size of receive buffer
|
||||
* Note: This is similar to `setsockopt` in POSIX for SO_RCVBUF
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_set_recv_buf_size(int32_t arg0,
|
||||
int32_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_set_recv_buf_size")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_set_recv_buf_size(__wasi_fd_t fd, __wasi_size_t size)
|
||||
{
|
||||
return (__wasi_errno_t)
|
||||
__imported_wasi_snapshot_preview1_sock_set_recv_buf_size((int32_t)fd,
|
||||
(int32_t)size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable address reuse on a socket
|
||||
* Note: This is similar to `setsockopt` in POSIX for SO_REUSEADDR
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_set_reuse_addr(int32_t arg0,
|
||||
int32_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_set_reuse_addr")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_set_reuse_addr(__wasi_fd_t fd, uint8_t reuse)
|
||||
{
|
||||
return (__wasi_errno_t)
|
||||
__imported_wasi_snapshot_preview1_sock_set_reuse_addr((int32_t)fd,
|
||||
(int32_t)reuse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable port reuse on a socket
|
||||
* Note: This is similar to `setsockopt` in POSIX for SO_REUSEPORT
|
||||
*/
|
||||
int32_t
|
||||
__imported_wasi_snapshot_preview1_sock_set_reuse_port(int32_t arg0,
|
||||
int32_t arg1)
|
||||
__attribute__((__import_module__("wasi_snapshot_preview1"),
|
||||
__import_name__("sock_set_reuse_port")));
|
||||
|
||||
static inline __wasi_errno_t
|
||||
__wasi_sock_set_reuse_port(__wasi_fd_t fd, uint8_t reuse)
|
||||
{
|
||||
return (__wasi_errno_t)
|
||||
__imported_wasi_snapshot_preview1_sock_set_reuse_port((int32_t)fd,
|
||||
(int32_t)reuse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set size of send buffer
|
||||
* 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)
|
||||
__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)
|
||||
{
|
||||
return (__wasi_errno_t)
|
||||
__imported_wasi_snapshot_preview1_sock_set_send_buf_size((int32_t)fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
9
core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake
Normal file
9
core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake
Normal file
@ -0,0 +1,9 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
cmake_minimum_required (VERSION 2.8...3.16)
|
||||
|
||||
project(socket_wasi_ext)
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC ${CMAKE_CURRENT_LIST_DIR}/src/wasi/wasi_socket_ext.c)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc/)
|
||||
180
core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c
Normal file
180
core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <wasi/api.h>
|
||||
#include <wasi_socket_ext.h>
|
||||
|
||||
#define HANDLE_ERROR(error) \
|
||||
if (error != __WASI_ERRNO_SUCCESS) { \
|
||||
errno = error; \
|
||||
return -1; \
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
static __wasi_errno_t
|
||||
sockaddr_to_wasi_addr(const struct sockaddr *sock_addr, socklen_t addrlen,
|
||||
__wasi_addr_t *wasi_addr)
|
||||
{
|
||||
__wasi_errno_t ret = __WASI_ERRNO_SUCCESS;
|
||||
if (AF_INET == sock_addr->sa_family) {
|
||||
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;
|
||||
}
|
||||
else {
|
||||
ret = __WASI_ERRNO_AFNOSUPPORT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __wasi_errno_t
|
||||
sock_addr_remote(__wasi_fd_t fd, struct sockaddr *sock_addr, socklen_t *addrlen)
|
||||
{
|
||||
__wasi_addr_t wasi_addr = { 0 };
|
||||
__wasi_errno_t error;
|
||||
|
||||
error =
|
||||
__wasi_sock_addr_remote(fd, (uint8_t *)&wasi_addr, sizeof(wasi_addr));
|
||||
if (__WASI_ERRNO_SUCCESS != error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int
|
||||
accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
__wasi_addr_t wasi_addr = { 0 };
|
||||
__wasi_fd_t new_sockfd;
|
||||
__wasi_errno_t error;
|
||||
|
||||
error = __wasi_sock_accept(sockfd, &new_sockfd);
|
||||
HANDLE_ERROR(error)
|
||||
|
||||
// error = sock_addr_remote(new_sockfd, addr, addrlen);
|
||||
// HANDLE_ERROR(error)
|
||||
*addrlen = 0;
|
||||
|
||||
return new_sockfd;
|
||||
}
|
||||
|
||||
int
|
||||
bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
__wasi_addr_t wasi_addr = { 0 };
|
||||
__wasi_errno_t error;
|
||||
|
||||
error = sockaddr_to_wasi_addr(addr, addrlen, &wasi_addr);
|
||||
HANDLE_ERROR(error)
|
||||
|
||||
error = __wasi_sock_bind(sockfd, &wasi_addr);
|
||||
HANDLE_ERROR(error)
|
||||
|
||||
return __WASI_ERRNO_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
__wasi_addr_t wasi_addr = { 0 };
|
||||
__wasi_errno_t error;
|
||||
|
||||
error = sockaddr_to_wasi_addr(addr, addrlen, &wasi_addr);
|
||||
HANDLE_ERROR(error)
|
||||
|
||||
error = __wasi_sock_connect(sockfd, &wasi_addr);
|
||||
HANDLE_ERROR(error)
|
||||
|
||||
return __WASI_ERRNO_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
listen(int sockfd, int backlog)
|
||||
{
|
||||
__wasi_errno_t error = __wasi_sock_listen(sockfd, backlog);
|
||||
HANDLE_ERROR(error)
|
||||
return __WASI_ERRNO_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
socket(int domain, int type, int protocol)
|
||||
{
|
||||
// the stub of address pool fd
|
||||
__wasi_fd_t poolfd = -1;
|
||||
__wasi_fd_t sockfd;
|
||||
__wasi_errno_t error;
|
||||
__wasi_address_family_t af;
|
||||
__wasi_sock_type_t socktype;
|
||||
|
||||
if (AF_INET == domain) {
|
||||
af = INET4;
|
||||
}
|
||||
else if (AF_INET6 == domain) {
|
||||
af = INET6;
|
||||
}
|
||||
else {
|
||||
return __WASI_ERRNO_NOPROTOOPT;
|
||||
}
|
||||
|
||||
if (SOCK_DGRAM == type) {
|
||||
socktype = SOCKET_DGRAM;
|
||||
}
|
||||
else if (SOCK_STREAM == type) {
|
||||
socktype = SOCKET_STREAM;
|
||||
}
|
||||
else {
|
||||
return __WASI_ERRNO_NOPROTOOPT;
|
||||
}
|
||||
|
||||
error = __wasi_sock_open(poolfd, af, socktype, &sockfd);
|
||||
HANDLE_ERROR(error)
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
@ -50,6 +50,7 @@ typedef struct WASIContext {
|
||||
struct fd_table *curfds;
|
||||
struct fd_prestats *prestats;
|
||||
struct argv_environ_values *argv_environ;
|
||||
struct addr_pool *addr_pool;
|
||||
char *argv_buf;
|
||||
char **argv_list;
|
||||
char *env_buf;
|
||||
@ -83,6 +84,14 @@ wasi_ctx_get_prestats(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
|
||||
return wasi_ctx->prestats;
|
||||
}
|
||||
|
||||
static inline struct addr_pool *
|
||||
wasi_ctx_get_addr_pool(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
|
||||
{
|
||||
if (!wasi_ctx)
|
||||
return NULL;
|
||||
return wasi_ctx->addr_pool;
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf)
|
||||
{
|
||||
@ -987,112 +996,277 @@ wasi_random_get(wasm_exec_env_t exec_env, void *buf, uint32 buf_len)
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data,
|
||||
uint32 ri_data_len, wasi_riflags_t ri_flags,
|
||||
uint32 *ro_datalen_app, wasi_roflags_t *ro_flags)
|
||||
wasi_sock_accept(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_fd_t *fd_new)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
|
||||
struct fd_table *curfds = NULL;
|
||||
|
||||
if (!wasi_ctx)
|
||||
return __WASI_EACCES;
|
||||
|
||||
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
|
||||
|
||||
return wasi_ssp_sock_accept(curfds, fd, fd_new);
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_addr_local(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *buf,
|
||||
wasi_size_t buf_len)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
|
||||
struct fd_table *curfds = NULL;
|
||||
|
||||
if (!wasi_ctx)
|
||||
return __WASI_EACCES;
|
||||
|
||||
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
|
||||
|
||||
return wasi_ssp_sock_addr_local(curfds, fd, buf, buf_len);
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_addr_remote(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *buf,
|
||||
wasi_size_t buf_len)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
|
||||
struct fd_table *curfds = NULL;
|
||||
|
||||
if (!wasi_ctx)
|
||||
return __WASI_EACCES;
|
||||
|
||||
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
|
||||
|
||||
return wasi_ssp_sock_addr_remote(curfds, fd, buf, buf_len);
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_addr_resolve(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *host,
|
||||
wasi_ip_port_t port, uint8 *buf, wasi_size_t size)
|
||||
{
|
||||
return __WASI_ENOSYS;
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_bind(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
|
||||
struct fd_table *curfds = NULL;
|
||||
struct addr_pool *addr_pool = NULL;
|
||||
|
||||
if (!wasi_ctx)
|
||||
return __WASI_EACCES;
|
||||
|
||||
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
|
||||
addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx);
|
||||
|
||||
return wasi_ssp_sock_bind(curfds, addr_pool, fd, addr);
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_close(wasm_exec_env_t exec_env, wasi_fd_t fd)
|
||||
{
|
||||
return __WASI_ENOSYS;
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
|
||||
struct fd_table *curfds = NULL;
|
||||
struct addr_pool *addr_pool = NULL;
|
||||
|
||||
if (!wasi_ctx)
|
||||
return __WASI_EACCES;
|
||||
|
||||
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
|
||||
addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx);
|
||||
|
||||
return wasi_ssp_sock_connect(curfds, addr_pool, fd, addr);
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_get_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
|
||||
wasi_size_t *size)
|
||||
{
|
||||
return __WASI_ENOSYS;
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_get_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *reuse)
|
||||
{
|
||||
return __WASI_ENOSYS;
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_get_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *reuse)
|
||||
{
|
||||
return __WASI_ENOSYS;
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_get_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
|
||||
wasi_size_t *size)
|
||||
{
|
||||
return __WASI_ENOSYS;
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_listen(wasm_exec_env_t exec_env, wasi_fd_t fd, uint32 backlog)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
|
||||
struct fd_table *curfds = NULL;
|
||||
|
||||
if (!wasi_ctx)
|
||||
return __WASI_EACCES;
|
||||
|
||||
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
|
||||
|
||||
return wasi_ssp_sock_listen(curfds, fd, backlog);
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_open(wasm_exec_env_t exec_env, wasi_fd_t poolfd,
|
||||
wasi_address_family_t af, wasi_sock_type_t socktype,
|
||||
wasi_fd_t *sockfd)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
|
||||
struct fd_table *curfds = NULL;
|
||||
|
||||
if (!wasi_ctx)
|
||||
return __WASI_EACCES;
|
||||
|
||||
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
|
||||
|
||||
return wasi_ssp_sock_open(curfds, poolfd, af, socktype, sockfd);
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_set_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
|
||||
wasi_size_t size)
|
||||
{
|
||||
return __WASI_ENOSYS;
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_set_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 reuse)
|
||||
{
|
||||
return __WASI_ENOSYS;
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_set_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 reuse)
|
||||
{
|
||||
return __WASI_ENOSYS;
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_set_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
|
||||
wasi_size_t size)
|
||||
{
|
||||
return __WASI_ENOSYS;
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data,
|
||||
uint32 ri_data_len, wasi_riflags_t ri_flags, uint32 *ro_data_len,
|
||||
wasi_roflags_t *ro_flags)
|
||||
{
|
||||
/**
|
||||
* ri_data_len is the length of a list of iovec_app_t, which head is
|
||||
* ri_data. ro_data_len is the number of bytes received
|
||||
**/
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
|
||||
struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
|
||||
wasi_iovec_t *iovec, *iovec_begin;
|
||||
uint64 total_size;
|
||||
size_t ro_datalen;
|
||||
uint32 i;
|
||||
wasi_errno_t err;
|
||||
|
||||
if (!wasi_ctx)
|
||||
return (wasi_errno_t)-1;
|
||||
return __WASI_EINVAL;
|
||||
|
||||
total_size = sizeof(iovec_app_t) * (uint64)ri_data_len;
|
||||
if (!validate_native_addr(ro_datalen_app, (uint32)sizeof(uint32))
|
||||
if (!validate_native_addr(ro_data_len, (uint32)sizeof(uint32))
|
||||
|| !validate_native_addr(ro_flags, (uint32)sizeof(wasi_roflags_t))
|
||||
|| total_size >= UINT32_MAX
|
||||
|| !validate_native_addr(ri_data, (uint32)total_size))
|
||||
return (wasi_errno_t)-1;
|
||||
return __WASI_EINVAL;
|
||||
|
||||
total_size = sizeof(wasi_iovec_t) * (uint64)ri_data_len;
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(iovec_begin = wasm_runtime_malloc((uint32)total_size)))
|
||||
return (wasi_errno_t)-1;
|
||||
/* recv ri_data one by one */
|
||||
*ro_data_len = 0;
|
||||
for (i = 0; i < ri_data_len; ri_data++, i++) {
|
||||
void *buf;
|
||||
size_t bytes_recv;
|
||||
|
||||
iovec = iovec_begin;
|
||||
|
||||
for (i = 0; i < ri_data_len; i++, ri_data++, iovec++) {
|
||||
if (!validate_app_addr(ri_data->buf_offset, ri_data->buf_len)) {
|
||||
err = (wasi_errno_t)-1;
|
||||
goto fail;
|
||||
return __WASI_EINVAL;
|
||||
}
|
||||
iovec->buf = (void *)addr_app_to_native(ri_data->buf_offset);
|
||||
iovec->buf_len = ri_data->buf_len;
|
||||
|
||||
buf = (void *)addr_app_to_native(ri_data->buf_offset);
|
||||
err = wasmtime_ssp_sock_recv(curfds, sock, buf, ri_data->buf_len,
|
||||
&bytes_recv);
|
||||
if (err != __WASI_ESUCCESS) {
|
||||
return err;
|
||||
}
|
||||
*ro_data_len += bytes_recv;
|
||||
}
|
||||
|
||||
err = wasmtime_ssp_sock_recv(curfds, sock, iovec_begin, ri_data_len,
|
||||
ri_flags, &ro_datalen, ro_flags);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
*(uint32 *)ro_datalen_app = (uint32)ro_datalen;
|
||||
|
||||
/* success */
|
||||
err = 0;
|
||||
|
||||
fail:
|
||||
wasm_runtime_free(iovec_begin);
|
||||
return err;
|
||||
*ro_flags = ri_flags;
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock,
|
||||
const iovec_app_t *si_data, uint32 si_data_len,
|
||||
wasi_siflags_t si_flags, uint32 *so_datalen_app)
|
||||
wasi_siflags_t si_flags, uint32 *so_data_len)
|
||||
{
|
||||
/**
|
||||
* si_data_len is the length of a list of iovec_app_t, which head is
|
||||
* si_data. so_data_len is the number of bytes sent
|
||||
**/
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
|
||||
struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
|
||||
wasi_ciovec_t *ciovec, *ciovec_begin;
|
||||
uint64 total_size;
|
||||
size_t so_datalen;
|
||||
uint32 i;
|
||||
wasi_errno_t err;
|
||||
|
||||
if (!wasi_ctx)
|
||||
return (wasi_errno_t)-1;
|
||||
return __WASI_EINVAL;
|
||||
|
||||
total_size = sizeof(iovec_app_t) * (uint64)si_data_len;
|
||||
if (!validate_native_addr(so_datalen_app, sizeof(uint32))
|
||||
if (!validate_native_addr(so_data_len, sizeof(uint32))
|
||||
|| total_size >= UINT32_MAX
|
||||
|| !validate_native_addr((void *)si_data, (uint32)total_size))
|
||||
return (wasi_errno_t)-1;
|
||||
return __WASI_EINVAL;
|
||||
|
||||
total_size = sizeof(wasi_ciovec_t) * (uint64)si_data_len;
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(ciovec_begin = wasm_runtime_malloc((uint32)total_size)))
|
||||
return (wasi_errno_t)-1;
|
||||
/* send si_data one by one */
|
||||
*so_data_len = 0;
|
||||
for (i = 0; i < si_data_len; i++, si_data++) {
|
||||
void *buf;
|
||||
size_t bytes_sent;
|
||||
|
||||
ciovec = ciovec_begin;
|
||||
|
||||
for (i = 0; i < si_data_len; i++, si_data++, ciovec++) {
|
||||
if (!validate_app_addr(si_data->buf_offset, si_data->buf_len)) {
|
||||
err = (wasi_errno_t)-1;
|
||||
goto fail;
|
||||
return __WASI_EINVAL;
|
||||
}
|
||||
ciovec->buf = (char *)addr_app_to_native(si_data->buf_offset);
|
||||
ciovec->buf_len = si_data->buf_len;
|
||||
|
||||
buf = (void *)addr_app_to_native(si_data->buf_offset);
|
||||
err = wasmtime_ssp_sock_send(curfds, sock, buf, si_data->buf_len,
|
||||
&bytes_sent);
|
||||
if (err != __WASI_ESUCCESS) {
|
||||
return err;
|
||||
}
|
||||
*so_data_len += bytes_sent;
|
||||
}
|
||||
|
||||
err = wasmtime_ssp_sock_send(curfds, sock, ciovec_begin, si_data_len,
|
||||
si_flags, &so_datalen);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
*so_datalen_app = (uint32)so_datalen;
|
||||
|
||||
/* success */
|
||||
err = 0;
|
||||
|
||||
fail:
|
||||
wasm_runtime_free(ciovec_begin);
|
||||
return err;
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
@ -1103,9 +1277,9 @@ wasi_sock_shutdown(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sdflags_t how)
|
||||
struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
|
||||
|
||||
if (!wasi_ctx)
|
||||
return (wasi_errno_t)-1;
|
||||
return __WASI_EINVAL;
|
||||
|
||||
return wasmtime_ssp_sock_shutdown(curfds, sock, how);
|
||||
return wasmtime_ssp_sock_shutdown(curfds, sock);
|
||||
}
|
||||
|
||||
static wasi_errno_t
|
||||
@ -1161,8 +1335,25 @@ static NativeSymbol native_symbols_libc_wasi[] = {
|
||||
REG_NATIVE_FUNC(proc_exit, "(i)"),
|
||||
REG_NATIVE_FUNC(proc_raise, "(i)i"),
|
||||
REG_NATIVE_FUNC(random_get, "(*~)i"),
|
||||
REG_NATIVE_FUNC(sock_accept, "(i*)i"),
|
||||
REG_NATIVE_FUNC(sock_addr_local, "(i*i)i"),
|
||||
REG_NATIVE_FUNC(sock_addr_remote, "(i*i)i"),
|
||||
REG_NATIVE_FUNC(sock_addr_resolve, "(i*i*i)i"),
|
||||
REG_NATIVE_FUNC(sock_bind, "(i*)i"),
|
||||
REG_NATIVE_FUNC(sock_close, "(i)i"),
|
||||
REG_NATIVE_FUNC(sock_connect, "(i*)i"),
|
||||
REG_NATIVE_FUNC(sock_get_recv_buf_size, "(i*)i"),
|
||||
REG_NATIVE_FUNC(sock_get_reuse_addr, "(i*)i"),
|
||||
REG_NATIVE_FUNC(sock_get_reuse_port, "(i*)i"),
|
||||
REG_NATIVE_FUNC(sock_get_send_buf_size, "(i*)i"),
|
||||
REG_NATIVE_FUNC(sock_listen, "(ii)i"),
|
||||
REG_NATIVE_FUNC(sock_open, "(iii*)i"),
|
||||
REG_NATIVE_FUNC(sock_recv, "(i*ii**)i"),
|
||||
REG_NATIVE_FUNC(sock_send, "(i*ii*)i"),
|
||||
REG_NATIVE_FUNC(sock_set_recv_buf_size, "(ii)i"),
|
||||
REG_NATIVE_FUNC(sock_set_reuse_addr, "(ii)i"),
|
||||
REG_NATIVE_FUNC(sock_set_reuse_port, "(ii)i"),
|
||||
REG_NATIVE_FUNC(sock_set_send_buf_size, "(ii)i"),
|
||||
REG_NATIVE_FUNC(sock_shutdown, "(ii)i"),
|
||||
REG_NATIVE_FUNC(sched_yield, "()i"),
|
||||
};
|
||||
|
||||
@ -13,38 +13,43 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef __wasi_errno_t wasi_errno_t;
|
||||
typedef __wasi_fd_t wasi_fd_t;
|
||||
typedef __wasi_clockid_t wasi_clockid_t;
|
||||
typedef __wasi_timestamp_t wasi_timestamp_t;
|
||||
typedef __wasi_prestat_t wasi_prestat_t;
|
||||
typedef __wasi_iovec_t wasi_iovec_t;
|
||||
typedef __wasi_ciovec_t wasi_ciovec_t;
|
||||
typedef __wasi_filetype_t wasi_filetype_t;
|
||||
typedef __wasi_filesize_t wasi_filesize_t;
|
||||
typedef __wasi_filedelta_t wasi_filedelta_t;
|
||||
typedef __wasi_whence_t wasi_whence_t;
|
||||
typedef __wasi_fdstat_t wasi_fdstat_t;
|
||||
typedef __wasi_fdflags_t wasi_fdflags_t;
|
||||
typedef __wasi_rights_t wasi_rights_t;
|
||||
typedef __wasi_address_family_t wasi_address_family_t;
|
||||
typedef __wasi_addr_t wasi_addr_t;
|
||||
typedef __wasi_advice_t wasi_advice_t;
|
||||
typedef __wasi_lookupflags_t wasi_lookupflags_t;
|
||||
typedef __wasi_oflags_t wasi_oflags_t;
|
||||
typedef __wasi_ciovec_t wasi_ciovec_t;
|
||||
typedef __wasi_clockid_t wasi_clockid_t;
|
||||
typedef __wasi_dircookie_t wasi_dircookie_t;
|
||||
typedef __wasi_filestat_t wasi_filestat_t;
|
||||
typedef __wasi_fstflags_t wasi_fstflags_t;
|
||||
typedef __wasi_subscription_t wasi_subscription_t;
|
||||
typedef __wasi_errno_t wasi_errno_t;
|
||||
typedef __wasi_event_t wasi_event_t;
|
||||
typedef __wasi_exitcode_t wasi_exitcode_t;
|
||||
typedef __wasi_signal_t wasi_signal_t;
|
||||
typedef __wasi_riflags_t wasi_riflags_t;
|
||||
typedef __wasi_roflags_t wasi_roflags_t;
|
||||
typedef __wasi_siflags_t wasi_siflags_t;
|
||||
typedef __wasi_sdflags_t wasi_sdflags_t;
|
||||
typedef __wasi_fdflags_t wasi_fdflags_t;
|
||||
typedef __wasi_fdstat_t wasi_fdstat_t;
|
||||
typedef __wasi_fd_t wasi_fd_t;
|
||||
typedef __wasi_filedelta_t wasi_filedelta_t;
|
||||
typedef __wasi_filesize_t wasi_filesize_t;
|
||||
typedef __wasi_filestat_t wasi_filestat_t;
|
||||
typedef __wasi_filetype_t wasi_filetype_t;
|
||||
typedef __wasi_fstflags_t wasi_fstflags_t;
|
||||
typedef __wasi_iovec_t wasi_iovec_t;
|
||||
typedef __wasi_ip_port_t wasi_ip_port_t;
|
||||
typedef __wasi_lookupflags_t wasi_lookupflags_t;
|
||||
typedef __wasi_oflags_t wasi_oflags_t;
|
||||
typedef __wasi_preopentype_t wasi_preopentype_t;
|
||||
typedef __wasi_prestat_t wasi_prestat_t;
|
||||
typedef __wasi_riflags_t wasi_riflags_t;
|
||||
typedef __wasi_rights_t wasi_rights_t;
|
||||
typedef __wasi_roflags_t wasi_roflags_t;
|
||||
typedef __wasi_sdflags_t wasi_sdflags_t;
|
||||
typedef __wasi_siflags_t wasi_siflags_t;
|
||||
typedef __wasi_signal_t wasi_signal_t;
|
||||
typedef __wasi_size_t wasi_size_t;
|
||||
typedef __wasi_sock_type_t wasi_sock_type_t;
|
||||
typedef __wasi_subscription_t wasi_subscription_t;
|
||||
typedef __wasi_timestamp_t wasi_timestamp_t;
|
||||
typedef __wasi_whence_t wasi_whence_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of _LIBC_WASI_WRAPPER_H */
|
||||
#endif /* end of _LIBC_WASI_WRAPPER_H */
|
||||
@ -49,6 +49,9 @@ _Static_assert(_Alignof(int64_t) == 8, "non-wasi data layout");
|
||||
_Static_assert(_Alignof(uint64_t) == 8, "non-wasi data layout");
|
||||
#endif
|
||||
|
||||
typedef uint32_t __wasi_size_t;
|
||||
_Static_assert(_Alignof(__wasi_size_t) == 4, "non-wasi data layout");
|
||||
|
||||
typedef uint8_t __wasi_advice_t;
|
||||
#define __WASI_ADVICE_NORMAL (0)
|
||||
#define __WASI_ADVICE_SEQUENTIAL (1)
|
||||
@ -211,35 +214,44 @@ typedef uint64_t __wasi_rights_t;
|
||||
* Observe that WASI defines rights in the plural form
|
||||
* TODO: refactor to use RIGHTS instead of RIGHT
|
||||
*/
|
||||
#define __WASI_RIGHT_FD_DATASYNC ((__wasi_rights_t)(1 << 0))
|
||||
#define __WASI_RIGHT_FD_READ ((__wasi_rights_t)(1 << 1))
|
||||
#define __WASI_RIGHT_FD_SEEK ((__wasi_rights_t)(1 << 2))
|
||||
#define __WASI_RIGHT_FD_FDSTAT_SET_FLAGS ((__wasi_rights_t)(1 << 3))
|
||||
#define __WASI_RIGHT_FD_SYNC ((__wasi_rights_t)(1 << 4))
|
||||
#define __WASI_RIGHT_FD_TELL ((__wasi_rights_t)(1 << 5))
|
||||
#define __WASI_RIGHT_FD_WRITE ((__wasi_rights_t)(1 << 6))
|
||||
#define __WASI_RIGHT_FD_ADVISE ((__wasi_rights_t)(1 << 7))
|
||||
#define __WASI_RIGHT_FD_ALLOCATE ((__wasi_rights_t)(1 << 8))
|
||||
#define __WASI_RIGHT_PATH_CREATE_DIRECTORY ((__wasi_rights_t)(1 << 9))
|
||||
#define __WASI_RIGHT_PATH_CREATE_FILE ((__wasi_rights_t)(1 << 10))
|
||||
#define __WASI_RIGHT_PATH_LINK_SOURCE ((__wasi_rights_t)(1 << 11))
|
||||
#define __WASI_RIGHT_PATH_LINK_TARGET ((__wasi_rights_t)(1 << 12))
|
||||
#define __WASI_RIGHT_PATH_OPEN ((__wasi_rights_t)(1 << 13))
|
||||
#define __WASI_RIGHT_FD_READDIR ((__wasi_rights_t)(1 << 14))
|
||||
#define __WASI_RIGHT_PATH_READLINK ((__wasi_rights_t)(1 << 15))
|
||||
#define __WASI_RIGHT_PATH_RENAME_SOURCE ((__wasi_rights_t)(1 << 16))
|
||||
#define __WASI_RIGHT_PATH_RENAME_TARGET ((__wasi_rights_t)(1 << 17))
|
||||
#define __WASI_RIGHT_PATH_FILESTAT_GET ((__wasi_rights_t)(1 << 18))
|
||||
#define __WASI_RIGHT_PATH_FILESTAT_SET_SIZE ((__wasi_rights_t)(1 << 19))
|
||||
#define __WASI_RIGHT_PATH_FILESTAT_SET_TIMES ((__wasi_rights_t)(1 << 20))
|
||||
#define __WASI_RIGHT_FD_FILESTAT_GET ((__wasi_rights_t)(1 << 21))
|
||||
#define __WASI_RIGHT_FD_FILESTAT_SET_SIZE ((__wasi_rights_t)(1 << 22))
|
||||
#define __WASI_RIGHT_FD_FILESTAT_SET_TIMES ((__wasi_rights_t)(1 << 23))
|
||||
#define __WASI_RIGHT_PATH_SYMLINK ((__wasi_rights_t)(1 << 24))
|
||||
#define __WASI_RIGHT_PATH_REMOVE_DIRECTORY ((__wasi_rights_t)(1 << 25))
|
||||
#define __WASI_RIGHT_PATH_UNLINK_FILE ((__wasi_rights_t)(1 << 26))
|
||||
#define __WASI_RIGHT_POLL_FD_READWRITE ((__wasi_rights_t)(1 << 27))
|
||||
#define __WASI_RIGHT_SOCK_SHUTDOWN ((__wasi_rights_t)(1 << 28))
|
||||
#define __WASI_RIGHT_FD_DATASYNC ((__wasi_rights_t)(UINT64_C(1) << 0))
|
||||
#define __WASI_RIGHT_FD_READ ((__wasi_rights_t)(UINT64_C(1) << 1))
|
||||
#define __WASI_RIGHT_FD_SEEK ((__wasi_rights_t)(UINT64_C(1) << 2))
|
||||
#define __WASI_RIGHT_FD_FDSTAT_SET_FLAGS ((__wasi_rights_t)(UINT64_C(1) << 3))
|
||||
#define __WASI_RIGHT_FD_SYNC ((__wasi_rights_t)(UINT64_C(1) << 4))
|
||||
#define __WASI_RIGHT_FD_TELL ((__wasi_rights_t)(UINT64_C(1) << 5))
|
||||
#define __WASI_RIGHT_FD_WRITE ((__wasi_rights_t)(UINT64_C(1) << 6))
|
||||
#define __WASI_RIGHT_FD_ADVISE ((__wasi_rights_t)(UINT64_C(1) << 7))
|
||||
#define __WASI_RIGHT_FD_ALLOCATE ((__wasi_rights_t)(UINT64_C(1) << 8))
|
||||
#define __WASI_RIGHT_PATH_CREATE_DIRECTORY ((__wasi_rights_t)(UINT64_C(1) << 9))
|
||||
#define __WASI_RIGHT_PATH_CREATE_FILE ((__wasi_rights_t)(UINT64_C(1) << 10))
|
||||
#define __WASI_RIGHT_PATH_LINK_SOURCE ((__wasi_rights_t)(UINT64_C(1) << 11))
|
||||
#define __WASI_RIGHT_PATH_LINK_TARGET ((__wasi_rights_t)(UINT64_C(1) << 12))
|
||||
#define __WASI_RIGHT_PATH_OPEN ((__wasi_rights_t)(UINT64_C(1) << 13))
|
||||
#define __WASI_RIGHT_FD_READDIR ((__wasi_rights_t)(UINT64_C(1) << 14))
|
||||
#define __WASI_RIGHT_PATH_READLINK ((__wasi_rights_t)(UINT64_C(1) << 15))
|
||||
#define __WASI_RIGHT_PATH_RENAME_SOURCE ((__wasi_rights_t)(UINT64_C(1) << 16))
|
||||
#define __WASI_RIGHT_PATH_RENAME_TARGET ((__wasi_rights_t)(UINT64_C(1) << 17))
|
||||
#define __WASI_RIGHT_PATH_FILESTAT_GET ((__wasi_rights_t)(UINT64_C(1) << 18))
|
||||
#define __WASI_RIGHT_PATH_FILESTAT_SET_SIZE ((__wasi_rights_t)(UINT64_C(1) << 19))
|
||||
#define __WASI_RIGHT_PATH_FILESTAT_SET_TIMES ((__wasi_rights_t)(UINT64_C(1) << 20))
|
||||
#define __WASI_RIGHT_FD_FILESTAT_GET ((__wasi_rights_t)(UINT64_C(1) << 21))
|
||||
#define __WASI_RIGHT_FD_FILESTAT_SET_SIZE ((__wasi_rights_t)(UINT64_C(1) << 22))
|
||||
#define __WASI_RIGHT_FD_FILESTAT_SET_TIMES ((__wasi_rights_t)(UINT64_C(1) << 23))
|
||||
#define __WASI_RIGHT_PATH_SYMLINK ((__wasi_rights_t)(UINT64_C(1) << 24))
|
||||
#define __WASI_RIGHT_PATH_REMOVE_DIRECTORY ((__wasi_rights_t)(UINT64_C(1) << 25))
|
||||
#define __WASI_RIGHT_PATH_UNLINK_FILE ((__wasi_rights_t)(UINT64_C(1) << 26))
|
||||
#define __WASI_RIGHT_POLL_FD_READWRITE ((__wasi_rights_t)(UINT64_C(1) << 27))
|
||||
#define __WASI_RIGHT_SOCK_CONNECT ((__wasi_rights_t)(UINT64_C(1) << 28))
|
||||
#define __WASI_RIGHT_SOCK_LISTEN ((__wasi_rights_t)(UINT64_C(1) << 29))
|
||||
#define __WASI_RIGHT_SOCK_BIND ((__wasi_rights_t)(UINT64_C(1) << 30))
|
||||
#define __WASI_RIGHT_SOCK_ACCEPT ((__wasi_rights_t)(UINT64_C(1) << 31))
|
||||
#define __WASI_RIGHT_SOCK_RECV ((__wasi_rights_t)(UINT64_C(1) << 32))
|
||||
#define __WASI_RIGHT_SOCK_SEND ((__wasi_rights_t)(UINT64_C(1) << 33))
|
||||
#define __WASI_RIGHT_SOCK_ADDR_LOCAL ((__wasi_rights_t)(UINT64_C(1) << 34))
|
||||
#define __WASI_RIGHT_SOCK_ADDR_REMOTE ((__wasi_rights_t)(UINT64_C(1) << 35))
|
||||
#define __WASI_RIGHT_SOCK_RECV_FROM ((__wasi_rights_t)(UINT64_C(1) << 36))
|
||||
#define __WASI_RIGHT_SOCK_SEND_TO ((__wasi_rights_t)(UINT64_C(1) << 37))
|
||||
|
||||
typedef uint16_t __wasi_roflags_t;
|
||||
#define __WASI_SOCK_RECV_DATA_TRUNCATED (0x0001)
|
||||
@ -301,6 +313,7 @@ typedef uint8_t __wasi_preopentype_t;
|
||||
struct fd_table;
|
||||
struct fd_prestats;
|
||||
struct argv_environ_values;
|
||||
struct addr_pool;
|
||||
|
||||
typedef struct __wasi_dirent_t {
|
||||
__wasi_dircookie_t d_next;
|
||||
@ -536,6 +549,55 @@ _Static_assert(_Alignof(__wasi_subscription_t) == 8, "witx calculated align");
|
||||
_Static_assert(offsetof(__wasi_subscription_t, userdata) == 0, "witx calculated offset");
|
||||
_Static_assert(offsetof(__wasi_subscription_t, u) == 8, "witx calculated offset");
|
||||
|
||||
/* keep syncing with wasi_socket_ext.h */
|
||||
typedef enum {
|
||||
SOCKET_DGRAM = 0,
|
||||
SOCKET_STREAM,
|
||||
} __wasi_sock_type_t;
|
||||
|
||||
typedef uint16_t __wasi_ip_port_t;
|
||||
|
||||
typedef enum { IPv4 = 0, IPv6 } __wasi_addr_type_t;
|
||||
|
||||
/* n0.n1.n2.n3 */
|
||||
typedef struct __wasi_addr_ip4_t {
|
||||
uint8_t n0;
|
||||
uint8_t n1;
|
||||
uint8_t n2;
|
||||
uint8_t n3;
|
||||
} __wasi_addr_ip4_t;
|
||||
|
||||
typedef struct __wasi_addr_ip4_port_t {
|
||||
__wasi_addr_ip4_t addr;
|
||||
__wasi_ip_port_t port;
|
||||
} __wasi_addr_ip4_port_t;
|
||||
|
||||
typedef struct __wasi_addr_ip6_t {
|
||||
uint16_t n0;
|
||||
uint16_t n1;
|
||||
uint16_t n2;
|
||||
uint16_t n3;
|
||||
uint16_t h0;
|
||||
uint16_t h1;
|
||||
uint16_t h2;
|
||||
uint16_t h3;
|
||||
} __wasi_addr_ip6_t;
|
||||
|
||||
typedef struct __wasi_addr_ip6_port_t {
|
||||
__wasi_addr_ip6_t addr;
|
||||
__wasi_ip_port_t port;
|
||||
} __wasi_addr_ip6_port_t;
|
||||
|
||||
typedef struct __wasi_addr_t {
|
||||
__wasi_addr_type_t kind;
|
||||
union {
|
||||
__wasi_addr_ip4_port_t ip4;
|
||||
__wasi_addr_ip6_port_t ip6;
|
||||
} addr;
|
||||
} __wasi_addr_t;
|
||||
|
||||
typedef enum { INET4 = 0, INET6 } __wasi_address_family_t;
|
||||
|
||||
#if defined(WASMTIME_SSP_WASI_API)
|
||||
#define WASMTIME_SSP_SYSCALL_NAME(name) \
|
||||
asm("__wasi_" #name)
|
||||
@ -920,16 +982,71 @@ __wasi_errno_t wasmtime_ssp_random_get(
|
||||
size_t buf_len
|
||||
) WASMTIME_SSP_SYSCALL_NAME(random_get) __attribute__((__warn_unused_result__));
|
||||
|
||||
__wasi_errno_t
|
||||
wasi_ssp_sock_accept(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t fd, __wasi_fd_t *fd_new
|
||||
) __attribute__((__warn_unused_result__));
|
||||
|
||||
__wasi_errno_t
|
||||
wasi_ssp_sock_addr_local(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len
|
||||
) __attribute__((__warn_unused_result__));
|
||||
|
||||
__wasi_errno_t
|
||||
wasi_ssp_sock_addr_remote(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len
|
||||
) __attribute__((__warn_unused_result__));
|
||||
|
||||
__wasi_errno_t
|
||||
wasi_ssp_sock_open(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype,
|
||||
__wasi_fd_t *sockfd
|
||||
) __attribute__((__warn_unused_result__));
|
||||
|
||||
__wasi_errno_t
|
||||
wasi_ssp_sock_bind(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds, struct addr_pool *addr_pool,
|
||||
#endif
|
||||
__wasi_fd_t fd, __wasi_addr_t *addr
|
||||
) __attribute__((__warn_unused_result__));
|
||||
|
||||
__wasi_errno_t
|
||||
wasi_ssp_sock_connect(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds, struct addr_pool *addr_pool,
|
||||
#endif
|
||||
__wasi_fd_t fd, __wasi_addr_t *addr
|
||||
) __attribute__((__warn_unused_result__));
|
||||
|
||||
__wasi_errno_t
|
||||
wasi_ssp_sock_listen(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t fd, __wasi_size_t backlog
|
||||
) __attribute__((__warn_unused_result__));
|
||||
|
||||
__wasi_errno_t wasmtime_ssp_sock_recv(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t sock,
|
||||
const __wasi_iovec_t *ri_data,
|
||||
size_t ri_data_len,
|
||||
__wasi_riflags_t ri_flags,
|
||||
size_t *ro_datalen,
|
||||
__wasi_roflags_t *ro_flags
|
||||
void *buf,
|
||||
size_t buf_len,
|
||||
size_t *recv_len
|
||||
) WASMTIME_SSP_SYSCALL_NAME(sock_recv) __attribute__((__warn_unused_result__));
|
||||
|
||||
__wasi_errno_t wasmtime_ssp_sock_send(
|
||||
@ -937,18 +1054,16 @@ __wasi_errno_t wasmtime_ssp_sock_send(
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t sock,
|
||||
const __wasi_ciovec_t *si_data,
|
||||
size_t si_data_len,
|
||||
__wasi_siflags_t si_flags,
|
||||
size_t *so_datalen
|
||||
const void *buf,
|
||||
size_t buf_len,
|
||||
size_t *sent_len
|
||||
) WASMTIME_SSP_SYSCALL_NAME(sock_send) __attribute__((__warn_unused_result__));
|
||||
|
||||
__wasi_errno_t wasmtime_ssp_sock_shutdown(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t sock,
|
||||
__wasi_sdflags_t how
|
||||
__wasi_fd_t sock
|
||||
) WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) __attribute__((__warn_unused_result__));
|
||||
|
||||
__wasi_errno_t wasmtime_ssp_sched_yield(void)
|
||||
|
||||
@ -60,6 +60,7 @@ static_assert(sizeof(struct iovec) == sizeof(__wasi_ciovec_t),
|
||||
static __thread struct fd_table *curfds;
|
||||
static __thread struct fd_prestats *prestats;
|
||||
static __thread struct argv_environ_values *argv_environ;
|
||||
static __thread struct addr_pool *addr_pool;
|
||||
#endif
|
||||
|
||||
// Converts a POSIX error code to a CloudABI error code.
|
||||
@ -2715,44 +2716,246 @@ wasmtime_ssp_random_get(void *buf, size_t nbyte)
|
||||
return 0;
|
||||
}
|
||||
|
||||
__wasi_errno_t
|
||||
wasi_ssp_sock_accept(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t fd, __wasi_fd_t *fd_new)
|
||||
{
|
||||
__wasi_filetype_t wasi_type;
|
||||
__wasi_rights_t max_base, max_inheriting;
|
||||
struct fd_object *fo;
|
||||
bh_socket_t new_sock;
|
||||
int ret;
|
||||
__wasi_errno_t error =
|
||||
fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ACCEPT, 0);
|
||||
if (error != __WASI_ESUCCESS)
|
||||
return error;
|
||||
|
||||
ret = os_socket_accept(fd_number(fo), &new_sock, NULL, NULL);
|
||||
fd_object_release(fo);
|
||||
if (ret == BHT_ERROR)
|
||||
return convert_errno(errno);
|
||||
|
||||
error = fd_determine_type_rights(new_sock, &wasi_type, &max_base,
|
||||
&max_inheriting);
|
||||
if (error != __WASI_ESUCCESS) {
|
||||
os_socket_close(ret);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = fd_table_insert_fd(curfds, new_sock, wasi_type, max_base,
|
||||
max_inheriting, fd_new);
|
||||
if (error != __WASI_ESUCCESS) {
|
||||
os_socket_close(ret);
|
||||
return error;
|
||||
}
|
||||
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
__wasi_errno_t
|
||||
wasi_ssp_sock_addr_local(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t fd, uint8 *buf, __wasi_size_t buf_len)
|
||||
{
|
||||
struct fd_object *fo;
|
||||
__wasi_errno_t error =
|
||||
fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_LOCAL, 0);
|
||||
if (error != __WASI_ESUCCESS)
|
||||
return error;
|
||||
|
||||
fd_object_release(fo);
|
||||
return __WASI_ENOSYS;
|
||||
}
|
||||
|
||||
__wasi_errno_t
|
||||
wasi_ssp_sock_addr_remote(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t fd, uint8 *buf, __wasi_size_t buf_len)
|
||||
{
|
||||
struct fd_object *fo;
|
||||
__wasi_errno_t error =
|
||||
fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_REMOTE, 0);
|
||||
if (error != __WASI_ESUCCESS)
|
||||
return error;
|
||||
|
||||
fd_object_release(fo);
|
||||
return __WASI_ENOSYS;
|
||||
}
|
||||
|
||||
__wasi_errno_t
|
||||
wasi_ssp_sock_bind(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds, struct addr_pool *addr_pool,
|
||||
#endif
|
||||
__wasi_fd_t fd, __wasi_addr_t *addr)
|
||||
{
|
||||
char buf[24] = { 0 };
|
||||
const char *format = "%u.%u.%u.%u";
|
||||
struct fd_object *fo;
|
||||
__wasi_errno_t error;
|
||||
int port = addr->addr.ip4.port;
|
||||
int ret;
|
||||
|
||||
snprintf(buf, 24, format, addr->addr.ip4.addr.n0, addr->addr.ip4.addr.n1,
|
||||
addr->addr.ip4.addr.n2, addr->addr.ip4.addr.n3);
|
||||
|
||||
if (!addr_pool_search(addr_pool, buf)) {
|
||||
return __WASI_EACCES;
|
||||
}
|
||||
|
||||
error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_BIND, 0);
|
||||
if (error != __WASI_ESUCCESS)
|
||||
return error;
|
||||
|
||||
ret = os_socket_bind(fd_number(fo), buf, &port);
|
||||
fd_object_release(fo);
|
||||
if (ret == BHT_ERROR) {
|
||||
return convert_errno(errno);
|
||||
}
|
||||
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
__wasi_errno_t
|
||||
wasi_ssp_sock_connect(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds, struct addr_pool *addr_pool,
|
||||
#endif
|
||||
__wasi_fd_t fd, __wasi_addr_t *addr)
|
||||
{
|
||||
char buf[24] = { 0 };
|
||||
const char *format = "%u.%u.%u.%u";
|
||||
struct fd_object *fo;
|
||||
__wasi_errno_t error;
|
||||
int ret;
|
||||
|
||||
snprintf(buf, 24, format, addr->addr.ip4.addr.n0, addr->addr.ip4.addr.n1,
|
||||
addr->addr.ip4.addr.n2, addr->addr.ip4.addr.n3);
|
||||
|
||||
if (!addr_pool_search(addr_pool, buf)) {
|
||||
return __WASI_EACCES;
|
||||
}
|
||||
|
||||
error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_BIND, 0);
|
||||
if (error != __WASI_ESUCCESS)
|
||||
return error;
|
||||
|
||||
ret = os_socket_connect(fd_number(fo), buf, addr->addr.ip4.port);
|
||||
fd_object_release(fo);
|
||||
if (ret == BHT_ERROR) {
|
||||
return convert_errno(errno);
|
||||
}
|
||||
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
__wasi_errno_t
|
||||
wasi_ssp_sock_listen(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t fd, __wasi_size_t backlog)
|
||||
{
|
||||
struct fd_object *fo;
|
||||
int ret;
|
||||
__wasi_errno_t error =
|
||||
fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_LISTEN, 0);
|
||||
if (error != __WASI_ESUCCESS)
|
||||
return error;
|
||||
|
||||
ret = os_socket_listen(fd_number(fo), backlog);
|
||||
fd_object_release(fo);
|
||||
if (ret == BHT_ERROR) {
|
||||
return convert_errno(errno);
|
||||
}
|
||||
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
__wasi_errno_t
|
||||
wasi_ssp_sock_open(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype,
|
||||
__wasi_fd_t *sockfd)
|
||||
{
|
||||
bh_socket_t sock;
|
||||
int tcp_or_udp = 0;
|
||||
int ret;
|
||||
__wasi_filetype_t wasi_type;
|
||||
__wasi_rights_t max_base, max_inheriting;
|
||||
__wasi_errno_t error;
|
||||
|
||||
(void)poolfd;
|
||||
|
||||
if (INET4 != af) {
|
||||
return __WASI_EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
tcp_or_udp = SOCKET_DGRAM == socktype ? 0 : 1;
|
||||
|
||||
ret = os_socket_create(&sock, tcp_or_udp);
|
||||
if (ret == BHT_ERROR) {
|
||||
return convert_errno(errno);
|
||||
}
|
||||
|
||||
error =
|
||||
fd_determine_type_rights(sock, &wasi_type, &max_base, &max_inheriting);
|
||||
if (error != __WASI_ESUCCESS) {
|
||||
os_socket_close(ret);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (SOCKET_DGRAM == socktype) {
|
||||
assert(wasi_type == __WASI_FILETYPE_SOCKET_DGRAM);
|
||||
}
|
||||
else {
|
||||
assert(wasi_type == __WASI_FILETYPE_SOCKET_STREAM);
|
||||
}
|
||||
|
||||
// TODO: base rights and inheriting rights ?
|
||||
error = fd_table_insert_fd(curfds, sock, wasi_type, max_base,
|
||||
max_inheriting, sockfd);
|
||||
if (error != __WASI_ESUCCESS) {
|
||||
os_socket_close(ret);
|
||||
return error;
|
||||
}
|
||||
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
__wasi_errno_t
|
||||
wasmtime_ssp_sock_recv(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t sock, const __wasi_iovec_t *ri_data, size_t ri_data_len,
|
||||
__wasi_riflags_t ri_flags, size_t *ro_datalen, __wasi_roflags_t *ro_flags)
|
||||
__wasi_fd_t sock, void *buf, size_t buf_len, size_t *recv_len)
|
||||
{
|
||||
// Convert input to msghdr.
|
||||
struct msghdr hdr = {
|
||||
.msg_iov = (struct iovec *)ri_data,
|
||||
.msg_iovlen = ri_data_len,
|
||||
};
|
||||
int nflags = 0;
|
||||
if ((ri_flags & __WASI_SOCK_RECV_PEEK) != 0)
|
||||
nflags |= MSG_PEEK;
|
||||
if ((ri_flags & __WASI_SOCK_RECV_WAITALL) != 0)
|
||||
nflags |= MSG_WAITALL;
|
||||
|
||||
struct fd_object *fo;
|
||||
__wasi_errno_t error =
|
||||
fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_READ, 0);
|
||||
__wasi_errno_t error;
|
||||
int ret;
|
||||
|
||||
error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_READ, 0);
|
||||
if (error != 0) {
|
||||
return error;
|
||||
}
|
||||
|
||||
ssize_t datalen = recvmsg(fd_number(fo), &hdr, nflags);
|
||||
ret = os_socket_recv(fd_number(fo), buf, buf_len);
|
||||
fd_object_release(fo);
|
||||
if (datalen < 0) {
|
||||
if (ret == BHT_ERROR) {
|
||||
return convert_errno(errno);
|
||||
}
|
||||
|
||||
// Convert msghdr to output.
|
||||
*ro_datalen = (size_t)datalen;
|
||||
*ro_flags = 0;
|
||||
if ((hdr.msg_flags & MSG_TRUNC) != 0)
|
||||
*ro_flags |= __WASI_SOCK_RECV_DATA_TRUNCATED;
|
||||
return 0;
|
||||
*recv_len = (size_t)ret;
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
__wasi_errno_t
|
||||
@ -2760,34 +2963,25 @@ wasmtime_ssp_sock_send(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t sock, const __wasi_ciovec_t *si_data, size_t si_data_len,
|
||||
__wasi_siflags_t si_flags, size_t *so_datalen) NO_LOCK_ANALYSIS
|
||||
__wasi_fd_t sock, const void *buf, size_t buf_len, size_t *sent_len)
|
||||
{
|
||||
// Convert input to msghdr.
|
||||
struct msghdr hdr = {
|
||||
.msg_iov = (struct iovec *)si_data,
|
||||
.msg_iovlen = si_data_len,
|
||||
};
|
||||
|
||||
// Attach file descriptors if present.
|
||||
__wasi_errno_t error;
|
||||
|
||||
// Send message.
|
||||
struct fd_object *fo;
|
||||
__wasi_errno_t error;
|
||||
int ret;
|
||||
|
||||
error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_WRITE, 0);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
ssize_t len = sendmsg(fd_number(fo), &hdr, 0);
|
||||
fd_object_release(fo);
|
||||
if (len < 0) {
|
||||
error = convert_errno(errno);
|
||||
}
|
||||
else {
|
||||
*so_datalen = (size_t)len;
|
||||
if (error != 0) {
|
||||
return error;
|
||||
}
|
||||
|
||||
out:
|
||||
return error;
|
||||
ret = os_socket_send(fd_number(fo), buf, buf_len);
|
||||
fd_object_release(fo);
|
||||
if (ret == BHT_ERROR) {
|
||||
return convert_errno(errno);
|
||||
}
|
||||
|
||||
*sent_len = (size_t)ret;
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
__wasi_errno_t
|
||||
@ -2795,34 +2989,22 @@ wasmtime_ssp_sock_shutdown(
|
||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||
struct fd_table *curfds,
|
||||
#endif
|
||||
__wasi_fd_t sock, __wasi_sdflags_t how)
|
||||
__wasi_fd_t sock)
|
||||
{
|
||||
int nhow;
|
||||
switch (how) {
|
||||
case __WASI_SHUT_RD:
|
||||
nhow = SHUT_RD;
|
||||
break;
|
||||
case __WASI_SHUT_WR:
|
||||
nhow = SHUT_WR;
|
||||
break;
|
||||
case __WASI_SHUT_RD | __WASI_SHUT_WR:
|
||||
nhow = SHUT_RDWR;
|
||||
break;
|
||||
default:
|
||||
return __WASI_EINVAL;
|
||||
}
|
||||
|
||||
struct fd_object *fo;
|
||||
__wasi_errno_t error =
|
||||
fd_object_get(curfds, &fo, sock, __WASI_RIGHT_SOCK_SHUTDOWN, 0);
|
||||
__wasi_errno_t error;
|
||||
int ret;
|
||||
|
||||
error = fd_object_get(curfds, &fo, sock, 0, 0);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
int ret = shutdown(fd_number(fo), nhow);
|
||||
ret = os_socket_shutdown(fd_number(fo));
|
||||
fd_object_release(fo);
|
||||
if (ret < 0)
|
||||
if (ret == BHT_ERROR)
|
||||
return convert_errno(errno);
|
||||
return 0;
|
||||
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
__wasi_errno_t
|
||||
@ -2943,3 +3125,88 @@ fd_prestats_destroy(struct fd_prestats *pt)
|
||||
wasm_runtime_free(pt->prestats);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
addr_pool_init(struct addr_pool *addr_pool)
|
||||
{
|
||||
addr_pool->next = NULL;
|
||||
addr_pool->addr = 0;
|
||||
addr_pool->mask = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
addr_pool_insert(struct addr_pool *addr_pool, const char *addr, uint8 mask)
|
||||
{
|
||||
struct addr_pool *cur = addr_pool;
|
||||
struct addr_pool *next;
|
||||
|
||||
if (!addr_pool) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(next = wasm_runtime_malloc(sizeof(struct addr_pool)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
next->next = NULL;
|
||||
next->mask = mask;
|
||||
if (os_socket_inet_network(addr, &next->addr) != BHT_OK) {
|
||||
wasm_runtime_free(next);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* attach with */
|
||||
while (cur->next) {
|
||||
cur = cur->next;
|
||||
}
|
||||
cur->next = next;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
compare_address(const struct addr_pool *addr_pool_entry, const char *addr)
|
||||
{
|
||||
/* host order */
|
||||
uint32 target;
|
||||
uint32 address = addr_pool_entry->addr;
|
||||
/* 0.0.0.0 means any address */
|
||||
if (0 == address) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (os_socket_inet_network(addr, &target) != BHT_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 mask = addr_pool_entry->mask;
|
||||
uint32 first_address = address & mask;
|
||||
uint32 last_address = address | (~mask);
|
||||
return first_address <= target && target <= last_address;
|
||||
}
|
||||
|
||||
bool
|
||||
addr_pool_search(struct addr_pool *addr_pool, const char *addr)
|
||||
{
|
||||
struct addr_pool *cur = addr_pool->next;
|
||||
|
||||
while (cur) {
|
||||
if (compare_address(cur, addr))
|
||||
return true;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
addr_pool_destroy(struct addr_pool *addr_pool)
|
||||
{
|
||||
struct addr_pool *cur = addr_pool->next;
|
||||
|
||||
while (cur) {
|
||||
struct addr_pool *next = cur->next;
|
||||
wasm_runtime_free(cur);
|
||||
cur = next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,6 +46,13 @@ struct argv_environ_values {
|
||||
size_t environ_count;
|
||||
};
|
||||
|
||||
struct addr_pool {
|
||||
struct addr_pool *next;
|
||||
/* addr and mask in host order */
|
||||
uint32 addr;
|
||||
uint8 mask;
|
||||
};
|
||||
|
||||
bool
|
||||
fd_table_init(struct fd_table *);
|
||||
bool
|
||||
@ -66,4 +73,13 @@ fd_table_destroy(struct fd_table *ft);
|
||||
void
|
||||
fd_prestats_destroy(struct fd_prestats *pt);
|
||||
|
||||
bool
|
||||
addr_pool_init(struct addr_pool *);
|
||||
bool
|
||||
addr_pool_insert(struct addr_pool *, const char *, uint8 mask);
|
||||
bool
|
||||
addr_pool_search(struct addr_pool *, const char *);
|
||||
void
|
||||
addr_pool_destroy(struct addr_pool *);
|
||||
|
||||
#endif
|
||||
|
||||
@ -32,7 +32,13 @@
|
||||
__WASI_RIGHT_FD_FILESTAT_SET_SIZE | \
|
||||
__WASI_RIGHT_PATH_SYMLINK | __WASI_RIGHT_PATH_UNLINK_FILE | \
|
||||
__WASI_RIGHT_PATH_REMOVE_DIRECTORY | \
|
||||
__WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_SHUTDOWN)
|
||||
__WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_CONNECT | \
|
||||
__WASI_RIGHT_SOCK_LISTEN | __WASI_RIGHT_SOCK_BIND | \
|
||||
__WASI_RIGHT_SOCK_ACCEPT | __WASI_RIGHT_SOCK_RECV | \
|
||||
__WASI_RIGHT_SOCK_SEND | __WASI_RIGHT_SOCK_ADDR_LOCAL | \
|
||||
__WASI_RIGHT_SOCK_ADDR_REMOTE | __WASI_RIGHT_SOCK_RECV_FROM | \
|
||||
__WASI_RIGHT_SOCK_SEND_TO)
|
||||
|
||||
|
||||
// Block and character device interaction is outside the scope of
|
||||
// CloudABI. Simply allow everything.
|
||||
@ -71,10 +77,15 @@
|
||||
#define RIGHTS_REGULAR_FILE_INHERITING 0
|
||||
|
||||
// Operations that apply to sockets and socket pairs.
|
||||
#define RIGHTS_SOCKET_BASE \
|
||||
(__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
|
||||
__WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FD_FILESTAT_GET | \
|
||||
__WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_SHUTDOWN)
|
||||
#define RIGHTS_SOCKET_BASE \
|
||||
(__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
|
||||
__WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FD_FILESTAT_GET | \
|
||||
__WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_CONNECT | \
|
||||
__WASI_RIGHT_SOCK_LISTEN | __WASI_RIGHT_SOCK_BIND | \
|
||||
__WASI_RIGHT_SOCK_ACCEPT | __WASI_RIGHT_SOCK_RECV | \
|
||||
__WASI_RIGHT_SOCK_SEND | __WASI_RIGHT_SOCK_ADDR_LOCAL | \
|
||||
__WASI_RIGHT_SOCK_ADDR_REMOTE | __WASI_RIGHT_SOCK_RECV_FROM | \
|
||||
__WASI_RIGHT_SOCK_SEND_TO)
|
||||
#define RIGHTS_SOCKET_INHERITING RIGHTS_ALL
|
||||
|
||||
// Operations that apply to TTYs.
|
||||
|
||||
Reference in New Issue
Block a user