mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-28 20:47:22 +00:00
Add support for IPv6 in WAMR (#1411)
For now this implementation only covers posix platforms, as defined in MVP #1336
This commit is contained in:
parent
0e17ab2f75
commit
0ffac101a1
|
@ -59,7 +59,7 @@ wasm_create_gdbserver(const char *host, int32 *port)
|
||||||
|
|
||||||
memset(server->receive_ctx, 0, sizeof(rsp_recv_context_t));
|
memset(server->receive_ctx, 0, sizeof(rsp_recv_context_t));
|
||||||
|
|
||||||
if (0 != os_socket_create(&listen_fd, 1)) {
|
if (0 != os_socket_create(&listen_fd, true, true)) {
|
||||||
LOG_ERROR("wasm gdb server error: create socket failed");
|
LOG_ERROR("wasm gdb server error: create socket failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,21 +31,38 @@ ipv4_addr_to_wasi_addr(uint32_t addr_num, uint16_t port, __wasi_addr_t *out)
|
||||||
out->addr.ip4.addr.n3 = (addr_num & 0x000000FF);
|
out->addr.ip4.addr.n3 = (addr_num & 0x000000FF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ipv6_addr_to_wasi_addr(uint16_t *addr, uint16_t port, __wasi_addr_t *out)
|
||||||
|
{
|
||||||
|
out->kind = IPv6;
|
||||||
|
out->addr.ip6.port = ntohs(port);
|
||||||
|
out->addr.ip6.addr.n0 = ntohs(addr[0]);
|
||||||
|
out->addr.ip6.addr.n1 = ntohs(addr[1]);
|
||||||
|
out->addr.ip6.addr.n2 = ntohs(addr[2]);
|
||||||
|
out->addr.ip6.addr.n3 = ntohs(addr[3]);
|
||||||
|
out->addr.ip6.addr.h0 = ntohs(addr[4]);
|
||||||
|
out->addr.ip6.addr.h1 = ntohs(addr[5]);
|
||||||
|
out->addr.ip6.addr.h2 = ntohs(addr[6]);
|
||||||
|
out->addr.ip6.addr.h3 = ntohs(addr[7]);
|
||||||
|
}
|
||||||
|
|
||||||
static __wasi_errno_t
|
static __wasi_errno_t
|
||||||
sockaddr_to_wasi_addr(const struct sockaddr *sock_addr, socklen_t addrlen,
|
sockaddr_to_wasi_addr(const struct sockaddr *sock_addr, socklen_t addrlen,
|
||||||
__wasi_addr_t *wasi_addr)
|
__wasi_addr_t *wasi_addr)
|
||||||
{
|
{
|
||||||
__wasi_errno_t ret = __WASI_ERRNO_SUCCESS;
|
__wasi_errno_t ret = __WASI_ERRNO_SUCCESS;
|
||||||
if (AF_INET == sock_addr->sa_family) {
|
if (AF_INET == sock_addr->sa_family) {
|
||||||
assert(sizeof(struct sockaddr_in) == addrlen);
|
assert(sizeof(struct sockaddr_in) <= addrlen);
|
||||||
|
|
||||||
ipv4_addr_to_wasi_addr(
|
ipv4_addr_to_wasi_addr(
|
||||||
((struct sockaddr_in *)sock_addr)->sin_addr.s_addr,
|
((struct sockaddr_in *)sock_addr)->sin_addr.s_addr,
|
||||||
((struct sockaddr_in *)sock_addr)->sin_port, wasi_addr);
|
((struct sockaddr_in *)sock_addr)->sin_port, wasi_addr);
|
||||||
}
|
}
|
||||||
else if (AF_INET6 == sock_addr->sa_family) {
|
else if (AF_INET6 == sock_addr->sa_family) {
|
||||||
// TODO: IPV6
|
assert(sizeof(struct sockaddr_in6) == addrlen);
|
||||||
ret = __WASI_ERRNO_AFNOSUPPORT;
|
ipv6_addr_to_wasi_addr(
|
||||||
|
(uint16_t *)((struct sockaddr_in6 *)sock_addr)->sin6_addr.s6_addr,
|
||||||
|
((struct sockaddr_in6 *)sock_addr)->sin6_port, wasi_addr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ret = __WASI_ERRNO_AFNOSUPPORT;
|
ret = __WASI_ERRNO_AFNOSUPPORT;
|
||||||
|
@ -78,8 +95,26 @@ wasi_addr_to_sockaddr(const __wasi_addr_t *wasi_addr,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IPv6:
|
case IPv6:
|
||||||
// TODO: IPV6
|
{
|
||||||
return __WASI_ERRNO_AFNOSUPPORT;
|
struct sockaddr_in6 sock_addr_in6 = { 0 };
|
||||||
|
uint16_t *addr_buf = (uint16_t *)sock_addr_in6.sin6_addr.s6_addr;
|
||||||
|
|
||||||
|
addr_buf[0] = htons(wasi_addr->addr.ip6.addr.n0);
|
||||||
|
addr_buf[1] = htons(wasi_addr->addr.ip6.addr.n1);
|
||||||
|
addr_buf[2] = htons(wasi_addr->addr.ip6.addr.n2);
|
||||||
|
addr_buf[3] = htons(wasi_addr->addr.ip6.addr.n3);
|
||||||
|
addr_buf[4] = htons(wasi_addr->addr.ip6.addr.h0);
|
||||||
|
addr_buf[5] = htons(wasi_addr->addr.ip6.addr.h1);
|
||||||
|
addr_buf[6] = htons(wasi_addr->addr.ip6.addr.h2);
|
||||||
|
addr_buf[7] = htons(wasi_addr->addr.ip6.addr.h3);
|
||||||
|
|
||||||
|
sock_addr_in6.sin6_family = AF_INET6;
|
||||||
|
sock_addr_in6.sin6_port = htons(wasi_addr->addr.ip6.port);
|
||||||
|
memcpy(sock_addr, &sock_addr_in6, sizeof(sock_addr_in6));
|
||||||
|
|
||||||
|
*addrlen = sizeof(sock_addr_in6);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return __WASI_ERRNO_AFNOSUPPORT;
|
return __WASI_ERRNO_AFNOSUPPORT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2948,6 +2948,35 @@ wasi_ssp_sock_addr_remote(
|
||||||
return __WASI_ESUCCESS;
|
return __WASI_ESUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wasi_addr_to_string(__wasi_addr_t *addr, char *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
if (addr->kind == IPv4) {
|
||||||
|
const char *format = "%u.%u.%u.%u";
|
||||||
|
|
||||||
|
assert(buflen >= 16);
|
||||||
|
|
||||||
|
snprintf(buf, buflen, format, addr->addr.ip4.addr.n0,
|
||||||
|
addr->addr.ip4.addr.n1, addr->addr.ip4.addr.n2,
|
||||||
|
addr->addr.ip4.addr.n3);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (addr->kind == IPv6) {
|
||||||
|
const char *format = "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x";
|
||||||
|
__wasi_addr_ip6_t ipv6 = addr->addr.ip6.addr;
|
||||||
|
|
||||||
|
assert(buflen >= 40);
|
||||||
|
|
||||||
|
snprintf(buf, buflen, format, ipv6.n0, ipv6.n1, ipv6.n2, ipv6.n3,
|
||||||
|
ipv6.h0, ipv6.h1, ipv6.h2, ipv6.h3);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
__wasi_errno_t
|
__wasi_errno_t
|
||||||
wasi_ssp_sock_bind(
|
wasi_ssp_sock_bind(
|
||||||
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
|
||||||
|
@ -2955,15 +2984,15 @@ wasi_ssp_sock_bind(
|
||||||
#endif
|
#endif
|
||||||
__wasi_fd_t fd, __wasi_addr_t *addr)
|
__wasi_fd_t fd, __wasi_addr_t *addr)
|
||||||
{
|
{
|
||||||
char buf[24] = { 0 };
|
char buf[48] = { 0 };
|
||||||
const char *format = "%u.%u.%u.%u";
|
|
||||||
struct fd_object *fo;
|
struct fd_object *fo;
|
||||||
__wasi_errno_t error;
|
__wasi_errno_t error;
|
||||||
int port = addr->addr.ip4.port;
|
int port = addr->kind == IPv4 ? addr->addr.ip4.port : addr->addr.ip6.port;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
snprintf(buf, 24, format, addr->addr.ip4.addr.n0, addr->addr.ip4.addr.n1,
|
if (!wasi_addr_to_string(addr, buf, sizeof(buf))) {
|
||||||
addr->addr.ip4.addr.n2, addr->addr.ip4.addr.n3);
|
return __WASI_EPROTONOSUPPORT;
|
||||||
|
}
|
||||||
|
|
||||||
if (!addr_pool_search(addr_pool, buf)) {
|
if (!addr_pool_search(addr_pool, buf)) {
|
||||||
return __WASI_EACCES;
|
return __WASI_EACCES;
|
||||||
|
@ -3017,7 +3046,8 @@ wasi_ssp_sock_addr_resolve(
|
||||||
addr_info_size < *max_info_size ? addr_info_size : *max_info_size;
|
addr_info_size < *max_info_size ? addr_info_size : *max_info_size;
|
||||||
|
|
||||||
for (size_t i = 0; i < actual_info_size; i++) {
|
for (size_t i = 0; i < actual_info_size; i++) {
|
||||||
addr_info[i].type = wamr_addr_info[i].is_tcp ? SOCK_STREAM : SOCK_DGRAM;
|
addr_info[i].type =
|
||||||
|
wamr_addr_info[i].is_tcp ? SOCKET_STREAM : SOCKET_DGRAM;
|
||||||
if (wamr_addr_info[i].is_ipv4) {
|
if (wamr_addr_info[i].is_ipv4) {
|
||||||
ipv4_addr_to_wasi_addr(*(uint32_t *)wamr_addr_info[i].addr,
|
ipv4_addr_to_wasi_addr(*(uint32_t *)wamr_addr_info[i].addr,
|
||||||
wamr_addr_info[i].port, &addr_info[i].addr);
|
wamr_addr_info[i].port, &addr_info[i].addr);
|
||||||
|
@ -3039,14 +3069,14 @@ wasi_ssp_sock_connect(
|
||||||
#endif
|
#endif
|
||||||
__wasi_fd_t fd, __wasi_addr_t *addr)
|
__wasi_fd_t fd, __wasi_addr_t *addr)
|
||||||
{
|
{
|
||||||
char buf[24] = { 0 };
|
char buf[48] = { 0 };
|
||||||
const char *format = "%u.%u.%u.%u";
|
|
||||||
struct fd_object *fo;
|
struct fd_object *fo;
|
||||||
__wasi_errno_t error;
|
__wasi_errno_t error;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
snprintf(buf, 24, format, addr->addr.ip4.addr.n0, addr->addr.ip4.addr.n1,
|
if (!wasi_addr_to_string(addr, buf, sizeof(buf))) {
|
||||||
addr->addr.ip4.addr.n2, addr->addr.ip4.addr.n3);
|
return __WASI_EPROTONOSUPPORT;
|
||||||
|
}
|
||||||
|
|
||||||
if (!addr_pool_search(addr_pool, buf)) {
|
if (!addr_pool_search(addr_pool, buf)) {
|
||||||
return __WASI_EACCES;
|
return __WASI_EACCES;
|
||||||
|
@ -3056,7 +3086,9 @@ wasi_ssp_sock_connect(
|
||||||
if (error != __WASI_ESUCCESS)
|
if (error != __WASI_ESUCCESS)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
ret = os_socket_connect(fd_number(fo), buf, addr->addr.ip4.port);
|
ret = os_socket_connect(fd_number(fo), buf,
|
||||||
|
addr->kind == IPv4 ? addr->addr.ip4.port
|
||||||
|
: addr->addr.ip6.port);
|
||||||
fd_object_release(fo);
|
fd_object_release(fo);
|
||||||
if (BHT_OK != ret) {
|
if (BHT_OK != ret) {
|
||||||
return convert_errno(errno);
|
return convert_errno(errno);
|
||||||
|
@ -3097,7 +3129,8 @@ wasi_ssp_sock_open(
|
||||||
__wasi_fd_t *sockfd)
|
__wasi_fd_t *sockfd)
|
||||||
{
|
{
|
||||||
bh_socket_t sock;
|
bh_socket_t sock;
|
||||||
int tcp_or_udp = 0;
|
bool is_tcp = SOCKET_DGRAM == socktype ? false : true;
|
||||||
|
bool is_ipv4 = INET6 ? false : true;
|
||||||
int ret;
|
int ret;
|
||||||
__wasi_filetype_t wasi_type;
|
__wasi_filetype_t wasi_type;
|
||||||
__wasi_rights_t max_base, max_inheriting;
|
__wasi_rights_t max_base, max_inheriting;
|
||||||
|
@ -3105,13 +3138,7 @@ wasi_ssp_sock_open(
|
||||||
|
|
||||||
(void)poolfd;
|
(void)poolfd;
|
||||||
|
|
||||||
if (INET4 != af) {
|
ret = os_socket_create(&sock, is_ipv4, is_tcp);
|
||||||
return __WASI_EAFNOSUPPORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
tcp_or_udp = SOCKET_DGRAM == socktype ? 0 : 1;
|
|
||||||
|
|
||||||
ret = os_socket_create(&sock, tcp_or_udp);
|
|
||||||
if (BHT_OK != ret) {
|
if (BHT_OK != ret) {
|
||||||
return convert_errno(errno);
|
return convert_errno(errno);
|
||||||
}
|
}
|
||||||
|
@ -3337,9 +3364,8 @@ fd_prestats_destroy(struct fd_prestats *pt)
|
||||||
bool
|
bool
|
||||||
addr_pool_init(struct addr_pool *addr_pool)
|
addr_pool_init(struct addr_pool *addr_pool)
|
||||||
{
|
{
|
||||||
addr_pool->next = NULL;
|
memset(addr_pool, 0, sizeof(*addr_pool));
|
||||||
addr_pool->addr = 0;
|
|
||||||
addr_pool->mask = 0;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3348,6 +3374,7 @@ addr_pool_insert(struct addr_pool *addr_pool, const char *addr, uint8 mask)
|
||||||
{
|
{
|
||||||
struct addr_pool *cur = addr_pool;
|
struct addr_pool *cur = addr_pool;
|
||||||
struct addr_pool *next;
|
struct addr_pool *next;
|
||||||
|
bh_inet_network_output_t target;
|
||||||
|
|
||||||
if (!addr_pool) {
|
if (!addr_pool) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -3359,9 +3386,20 @@ addr_pool_insert(struct addr_pool *addr_pool, const char *addr, uint8 mask)
|
||||||
|
|
||||||
next->next = NULL;
|
next->next = NULL;
|
||||||
next->mask = mask;
|
next->mask = mask;
|
||||||
if (os_socket_inet_network(addr, &next->addr) != BHT_OK) {
|
|
||||||
wasm_runtime_free(next);
|
if (os_socket_inet_network(true, addr, &target) != BHT_OK) {
|
||||||
return false;
|
// If parsing IPv4 fails, try IPv6
|
||||||
|
if (os_socket_inet_network(false, addr, &target) != BHT_OK) {
|
||||||
|
wasm_runtime_free(next);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
next->type = IPv6;
|
||||||
|
bh_memcpy_s(next->addr.ip6, sizeof(next->addr.ip6), target.ipv6,
|
||||||
|
sizeof(target.ipv6));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
next->type = IPv4;
|
||||||
|
next->addr.ip4 = target.ipv4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* attach with */
|
/* attach with */
|
||||||
|
@ -3372,47 +3410,106 @@ addr_pool_insert(struct addr_pool *addr_pool, const char *addr, uint8 mask)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static inline size_t
|
||||||
compare_address(const struct addr_pool *addr_pool_entry, const char *addr)
|
min(size_t a, size_t b)
|
||||||
{
|
{
|
||||||
/* host order */
|
return a > b ? b : a;
|
||||||
uint32 target;
|
}
|
||||||
uint32 address = addr_pool_entry->addr;
|
|
||||||
/* 0.0.0.0 means any address */
|
static void
|
||||||
if (0 == address) {
|
init_address_mask(uint8_t *buf, size_t buflen, size_t mask)
|
||||||
|
{
|
||||||
|
size_t element_size = sizeof(uint8_t) * 8;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < buflen; i++) {
|
||||||
|
if (mask <= i * element_size) {
|
||||||
|
buf[i] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
size_t offset = min(mask - i * element_size, element_size);
|
||||||
|
buf[i] = (~0u) << (element_size - offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* target must be in network byte order */
|
||||||
|
static bool
|
||||||
|
compare_address(const struct addr_pool *addr_pool_entry,
|
||||||
|
bh_inet_network_output_t *target)
|
||||||
|
{
|
||||||
|
uint8_t maskbuf[16] = { 0 };
|
||||||
|
uint8_t basebuf[16] = { 0 };
|
||||||
|
size_t addr_size;
|
||||||
|
uint8_t max_addr_mask;
|
||||||
|
|
||||||
|
if (addr_pool_entry->type == IPv4) {
|
||||||
|
uint32_t addr_ip4 = htonl(addr_pool_entry->addr.ip4);
|
||||||
|
bh_memcpy_s(basebuf, sizeof(addr_ip4), &addr_ip4, sizeof(addr_ip4));
|
||||||
|
addr_size = 4;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uint16_t partial_addr_ip6;
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
partial_addr_ip6 = htons(addr_pool_entry->addr.ip6[i]);
|
||||||
|
bh_memcpy_s(&basebuf[i * sizeof(partial_addr_ip6)],
|
||||||
|
sizeof(partial_addr_ip6), &partial_addr_ip6,
|
||||||
|
sizeof(partial_addr_ip6));
|
||||||
|
}
|
||||||
|
addr_size = 16;
|
||||||
|
}
|
||||||
|
max_addr_mask = addr_size * 8;
|
||||||
|
|
||||||
|
/* IPv4 0.0.0.0 or IPv6 :: means any address */
|
||||||
|
if (basebuf[0] == 0 && !memcmp(basebuf, basebuf + 1, addr_size - 1)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (os_socket_inet_network(addr, &target) != BHT_OK) {
|
/* No support for invalid mask value */
|
||||||
|
if (addr_pool_entry->mask > max_addr_mask) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32 max_mask_value = 32;
|
init_address_mask(maskbuf, addr_size, addr_pool_entry->mask);
|
||||||
/* no support for invalid mask values */
|
|
||||||
if (addr_pool_entry->mask > max_mask_value) {
|
for (size_t i = 0; i < addr_size; i++) {
|
||||||
return false;
|
uint8_t addr_mask = target->data[i] & maskbuf[i];
|
||||||
|
uint8_t range_mask = basebuf[i] & maskbuf[i];
|
||||||
|
if (addr_mask != range_mask) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert mask number into 32-bit mask value, i.e. mask /24 will be
|
return true;
|
||||||
converted to 4294967040 (binary: 11111111 11111111 11111111 00000000) */
|
|
||||||
uint32 mask = 0;
|
|
||||||
for (int i = 0; i < addr_pool_entry->mask; i++) {
|
|
||||||
mask |= 1 << (max_mask_value - 1 - i);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 first_address = address & mask;
|
|
||||||
uint32 last_address = address | (~mask);
|
|
||||||
return first_address <= target && target <= last_address;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
addr_pool_search(struct addr_pool *addr_pool, const char *addr)
|
addr_pool_search(struct addr_pool *addr_pool, const char *addr)
|
||||||
{
|
{
|
||||||
struct addr_pool *cur = addr_pool->next;
|
struct addr_pool *cur = addr_pool->next;
|
||||||
|
bh_inet_network_output_t target;
|
||||||
|
__wasi_addr_type_t addr_type;
|
||||||
|
|
||||||
|
if (os_socket_inet_network(true, addr, &target) != BHT_OK) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (os_socket_inet_network(false, addr, &target) != BHT_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
addr_type = IPv6;
|
||||||
|
for (i = 0; i < sizeof(target.ipv6) / sizeof(target.ipv6[0]); i++) {
|
||||||
|
target.ipv6[i] = htons(target.ipv6[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addr_type = IPv4;
|
||||||
|
target.ipv4 = htonl(target.ipv4);
|
||||||
|
}
|
||||||
|
|
||||||
while (cur) {
|
while (cur) {
|
||||||
if (compare_address(cur, addr))
|
if (cur->type == addr_type && compare_address(cur, &target)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,9 +47,13 @@ struct argv_environ_values {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct addr_pool {
|
struct addr_pool {
|
||||||
struct addr_pool *next;
|
|
||||||
/* addr and mask in host order */
|
/* addr and mask in host order */
|
||||||
uint32 addr;
|
union {
|
||||||
|
uint32 ip4;
|
||||||
|
uint16 ip6[8];
|
||||||
|
} addr;
|
||||||
|
struct addr_pool *next;
|
||||||
|
__wasi_addr_type_t type;
|
||||||
uint8 mask;
|
uint8 mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,28 +9,45 @@
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
static void
|
static bool
|
||||||
textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr_in *out)
|
textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr *out)
|
||||||
{
|
{
|
||||||
|
struct sockaddr_in *v4;
|
||||||
|
struct sockaddr_in6 *v6;
|
||||||
|
|
||||||
assert(textual);
|
assert(textual);
|
||||||
|
|
||||||
out->sin_family = AF_INET;
|
v4 = (struct sockaddr_in *)out;
|
||||||
out->sin_port = htons(port);
|
if (inet_pton(AF_INET, textual, &v4->sin_addr.s_addr) == 1) {
|
||||||
out->sin_addr.s_addr = inet_addr(textual);
|
v4->sin_family = AF_INET;
|
||||||
|
v4->sin_port = htons(port);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
v6 = (struct sockaddr_in6 *)out;
|
||||||
|
if (inet_pton(AF_INET6, textual, &v6->sin6_addr.s6_addr) == 1) {
|
||||||
|
v6->sin6_family = AF_INET6;
|
||||||
|
v6->sin6_port = htons(port);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
os_socket_create(bh_socket_t *sock, int tcp_or_udp)
|
os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp)
|
||||||
{
|
{
|
||||||
|
int af = is_ipv4 ? AF_INET : AF_INET6;
|
||||||
|
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
return BHT_ERROR;
|
return BHT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (1 == tcp_or_udp) {
|
if (is_tcp) {
|
||||||
*sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
*sock = socket(af, SOCK_STREAM, IPPROTO_TCP);
|
||||||
}
|
}
|
||||||
else if (0 == tcp_or_udp) {
|
else {
|
||||||
*sock = socket(AF_INET, SOCK_DGRAM, 0);
|
*sock = socket(af, SOCK_DGRAM, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (*sock == -1) ? BHT_ERROR : BHT_OK;
|
return (*sock == -1) ? BHT_ERROR : BHT_OK;
|
||||||
|
@ -39,7 +56,7 @@ os_socket_create(bh_socket_t *sock, int tcp_or_udp)
|
||||||
int
|
int
|
||||||
os_socket_bind(bh_socket_t socket, const char *host, int *port)
|
os_socket_bind(bh_socket_t socket, const char *host, int *port)
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_storage addr;
|
||||||
struct linger ling;
|
struct linger ling;
|
||||||
socklen_t socklen;
|
socklen_t socklen;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -60,7 +77,9 @@ os_socket_bind(bh_socket_t socket, const char *host, int *port)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
textual_addr_to_sockaddr(host, *port, &addr);
|
if (!textual_addr_to_sockaddr(host, *port, (struct sockaddr *)&addr)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
ret = bind(socket, (struct sockaddr *)&addr, sizeof(addr));
|
ret = bind(socket, (struct sockaddr *)&addr, sizeof(addr));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -72,7 +91,9 @@ os_socket_bind(bh_socket_t socket, const char *host, int *port)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
*port = ntohs(addr.sin_port);
|
*port = ntohs(addr.ss_family == AF_INET
|
||||||
|
? ((struct sockaddr_in *)&addr)->sin_port
|
||||||
|
: ((struct sockaddr_in6 *)&addr)->sin6_port);
|
||||||
|
|
||||||
return BHT_OK;
|
return BHT_OK;
|
||||||
|
|
||||||
|
@ -113,7 +134,7 @@ os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
|
||||||
struct sockaddr addr_tmp;
|
struct sockaddr addr_tmp;
|
||||||
unsigned int len = sizeof(struct sockaddr);
|
unsigned int len = sizeof(struct sockaddr);
|
||||||
|
|
||||||
*sock = accept(server_sock, (struct sockaddr *)&addr_tmp, &len);
|
*sock = accept(server_sock, &addr_tmp, &len);
|
||||||
|
|
||||||
if (*sock < 0) {
|
if (*sock < 0) {
|
||||||
return BHT_ERROR;
|
return BHT_ERROR;
|
||||||
|
@ -125,11 +146,13 @@ os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
|
||||||
int
|
int
|
||||||
os_socket_connect(bh_socket_t socket, const char *addr, int port)
|
os_socket_connect(bh_socket_t socket, const char *addr, int port)
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr_in = { 0 };
|
struct sockaddr_storage addr_in = { 0 };
|
||||||
socklen_t addr_len = sizeof(struct sockaddr_in);
|
socklen_t addr_len = sizeof(struct sockaddr_storage);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
textual_addr_to_sockaddr(addr, port, &addr_in);
|
if (!textual_addr_to_sockaddr(addr, port, (struct sockaddr *)&addr_in)) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
ret = connect(socket, (struct sockaddr *)&addr_in, addr_len);
|
ret = connect(socket, (struct sockaddr *)&addr_in, addr_len);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
|
@ -166,13 +189,28 @@ os_socket_shutdown(bh_socket_t socket)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
os_socket_inet_network(const char *cp, uint32 *out)
|
os_socket_inet_network(bool is_ipv4, const char *cp,
|
||||||
|
bh_inet_network_output_t *out)
|
||||||
{
|
{
|
||||||
if (!cp)
|
if (!cp)
|
||||||
return BHT_ERROR;
|
return BHT_ERROR;
|
||||||
|
|
||||||
/* Note: ntohl(INADDR_NONE) == INADDR_NONE */
|
if (is_ipv4) {
|
||||||
*out = ntohl(inet_addr(cp));
|
if (inet_pton(AF_INET, cp, &out->ipv4) != 1) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
/* Note: ntohl(INADDR_NONE) == INADDR_NONE */
|
||||||
|
out->ipv4 = ntohl(out->ipv4);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return BHT_OK;
|
return BHT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -296,12 +296,13 @@ os_sem_unlink(const char *name);
|
||||||
* Create a socket
|
* Create a socket
|
||||||
*
|
*
|
||||||
* @param sock [OUTPUT] the pointer of socket
|
* @param sock [OUTPUT] the pointer of socket
|
||||||
* @param tcp_or_udp 1 for tcp, 0 for udp
|
* @param is_ipv4 true for IPv4, false for IPv6
|
||||||
|
* @param is_tcp true for tcp, false for udp
|
||||||
*
|
*
|
||||||
* @return 0 if success, -1 otherwise
|
* @return 0 if success, -1 otherwise
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
os_socket_create(bh_socket_t *sock, int tcp_or_udp);
|
os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assign the address and port to the socket
|
* Assign the address and port to the socket
|
||||||
|
@ -412,17 +413,30 @@ os_socket_close(bh_socket_t socket);
|
||||||
int
|
int
|
||||||
os_socket_shutdown(bh_socket_t socket);
|
os_socket_shutdown(bh_socket_t socket);
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint32 ipv4;
|
||||||
|
uint16 ipv6[8];
|
||||||
|
uint8_t data[0];
|
||||||
|
} bh_inet_network_output_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* converts cp into a number in host byte order suitable for use as
|
* converts cp into a number in host byte order suitable for use as
|
||||||
* an Internet network address
|
* an Internet network address
|
||||||
*
|
*
|
||||||
* @param cp a string in IPv4 numbers-and-dots notation
|
* @param is_ipv4 a flag that indicates whether the string is an IPv4 or
|
||||||
|
* IPv6 address
|
||||||
*
|
*
|
||||||
* @return On success, the converted address is returned.
|
* @param cp a string in IPv4 numbers-and-dots notation or IPv6
|
||||||
|
* numbers-and-colons notation
|
||||||
|
*
|
||||||
|
* @param out an output buffer to store binary address
|
||||||
|
*
|
||||||
|
* @return On success, the function returns 0.
|
||||||
* If the input is invalid, -1 is returned
|
* If the input is invalid, -1 is returned
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
os_socket_inet_network(const char *cp, uint32 *out);
|
os_socket_inet_network(bool is_ipv4, const char *cp,
|
||||||
|
bh_inet_network_output_t *out);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t addr[16];
|
uint8_t addr[16];
|
||||||
|
|
|
@ -92,7 +92,7 @@ swap16(uint8 *pData)
|
||||||
*(pData + 1) = value;
|
*(pData + 1) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32
|
uint32
|
||||||
htonl(uint32 value)
|
htonl(uint32 value)
|
||||||
{
|
{
|
||||||
uint32 ret;
|
uint32 ret;
|
||||||
|
@ -111,7 +111,7 @@ ntohl(uint32 value)
|
||||||
return htonl(value);
|
return htonl(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16
|
uint16
|
||||||
htons(uint16 value)
|
htons(uint16 value)
|
||||||
{
|
{
|
||||||
uint16 ret;
|
uint16 ret;
|
||||||
|
@ -132,57 +132,96 @@ ntohs(uint16 value)
|
||||||
|
|
||||||
/* Coming from musl, under MIT license */
|
/* Coming from musl, under MIT license */
|
||||||
static int
|
static int
|
||||||
__inet_aton(const char *s0, struct in_addr *dest)
|
hexval(unsigned c)
|
||||||
{
|
{
|
||||||
const char *s = s0;
|
if (c - '0' < 10)
|
||||||
unsigned char *d = (void *)dest;
|
return c - '0';
|
||||||
unsigned long a[4] = { 0 };
|
c |= 32;
|
||||||
char *z;
|
if (c - 'a' < 6)
|
||||||
int i;
|
return c - 'a' + 10;
|
||||||
|
return -1;
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
a[i] = strtoul(s, &z, 0);
|
|
||||||
if (z == s || (*z && *z != '.') || !isdigit(*s))
|
|
||||||
return 0;
|
|
||||||
if (!*z)
|
|
||||||
break;
|
|
||||||
s = z + 1;
|
|
||||||
}
|
|
||||||
if (i == 4)
|
|
||||||
return 0;
|
|
||||||
switch (i) {
|
|
||||||
case 0:
|
|
||||||
a[1] = a[0] & 0xffffff;
|
|
||||||
a[0] >>= 24;
|
|
||||||
case 1:
|
|
||||||
a[2] = a[1] & 0xffff;
|
|
||||||
a[1] >>= 16;
|
|
||||||
case 2:
|
|
||||||
a[3] = a[2] & 0xff;
|
|
||||||
a[2] >>= 8;
|
|
||||||
}
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
if (a[i] > 255)
|
|
||||||
return 0;
|
|
||||||
d[i] = a[i];
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Coming from musl, under MIT license */
|
/* Coming from musl, under MIT license */
|
||||||
static int
|
static int
|
||||||
inet_addr(const char *p)
|
inet_pton(int af, const char *restrict s, void *restrict a0)
|
||||||
{
|
{
|
||||||
struct in_addr a;
|
uint16_t ip[8];
|
||||||
if (!__inet_aton(p, &a))
|
unsigned char *a = a0;
|
||||||
|
int i, j, v, d, brk = -1, need_v4 = 0;
|
||||||
|
|
||||||
|
if (af == AF_INET) {
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
for (v = j = 0; j < 3 && isdigit(s[j]); j++)
|
||||||
|
v = 10 * v + s[j] - '0';
|
||||||
|
if (j == 0 || (j > 1 && s[0] == '0') || v > 255)
|
||||||
|
return 0;
|
||||||
|
a[i] = v;
|
||||||
|
if (s[j] == 0 && i == 3)
|
||||||
|
return 1;
|
||||||
|
if (s[j] != '.')
|
||||||
|
return 0;
|
||||||
|
s += j + 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (af != AF_INET6) {
|
||||||
|
errno = EAFNOSUPPORT;
|
||||||
return -1;
|
return -1;
|
||||||
return a.s_addr;
|
}
|
||||||
|
|
||||||
|
if (*s == ':' && *++s != ':')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0;; i++) {
|
||||||
|
if (s[0] == ':' && brk < 0) {
|
||||||
|
brk = i;
|
||||||
|
ip[i & 7] = 0;
|
||||||
|
if (!*++s)
|
||||||
|
break;
|
||||||
|
if (i == 7)
|
||||||
|
return 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (v = j = 0; j < 4 && (d = hexval(s[j])) >= 0; j++)
|
||||||
|
v = 16 * v + d;
|
||||||
|
if (j == 0)
|
||||||
|
return 0;
|
||||||
|
ip[i & 7] = v;
|
||||||
|
if (!s[j] && (brk >= 0 || i == 7))
|
||||||
|
break;
|
||||||
|
if (i == 7)
|
||||||
|
return 0;
|
||||||
|
if (s[j] != ':') {
|
||||||
|
if (s[j] != '.' || (i < 6 && brk < 0))
|
||||||
|
return 0;
|
||||||
|
need_v4 = 1;
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s += j + 1;
|
||||||
|
}
|
||||||
|
if (brk >= 0) {
|
||||||
|
memmove(ip + brk + 7 - i, ip + brk, 2 * (i + 1 - brk));
|
||||||
|
for (j = 0; j < 7 - i; j++)
|
||||||
|
ip[brk + j] = 0;
|
||||||
|
}
|
||||||
|
for (j = 0; j < 8; j++) {
|
||||||
|
*a++ = ip[j] >> 8;
|
||||||
|
*a++ = ip[j];
|
||||||
|
}
|
||||||
|
if (need_v4 && inet_pton(AF_INET, (void *)s, a - 4) <= 0)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
inet_network(const char *p)
|
inet_addr(const char *p)
|
||||||
{
|
{
|
||||||
return ntohl(inet_addr(p));
|
struct in_addr a;
|
||||||
|
if (!inet_pton(AF_INET, p, &a))
|
||||||
|
return -1;
|
||||||
|
return a.s_addr;
|
||||||
}
|
}
|
||||||
/** In-enclave implementation of POSIX functions end **/
|
/** In-enclave implementation of POSIX functions end **/
|
||||||
|
|
||||||
|
@ -528,21 +567,30 @@ os_socket_connect(bh_socket_t socket, const char *addr, int port)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
os_socket_create(bh_socket_t *sock, int tcp_or_udp)
|
os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp)
|
||||||
{
|
{
|
||||||
|
int af;
|
||||||
|
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
return BHT_ERROR;
|
return BHT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (1 == tcp_or_udp) {
|
if (is_ipv4) {
|
||||||
if (ocall_socket(sock, AF_INET, SOCK_STREAM, IPPROTO_TCP)
|
af = AF_INET;
|
||||||
!= SGX_SUCCESS) {
|
}
|
||||||
|
else {
|
||||||
|
errno = ENOSYS;
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_tcp) {
|
||||||
|
if (ocall_socket(sock, af, SOCK_STREAM, IPPROTO_TCP) != SGX_SUCCESS) {
|
||||||
TRACE_OCALL_FAIL();
|
TRACE_OCALL_FAIL();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (0 == tcp_or_udp) {
|
else {
|
||||||
if (ocall_socket(sock, AF_INET, SOCK_DGRAM, 0) != SGX_SUCCESS) {
|
if (ocall_socket(sock, af, SOCK_DGRAM, 0) != SGX_SUCCESS) {
|
||||||
TRACE_OCALL_FAIL();
|
TRACE_OCALL_FAIL();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -557,12 +605,27 @@ os_socket_create(bh_socket_t *sock, int tcp_or_udp)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
os_socket_inet_network(const char *cp, uint32 *out)
|
os_socket_inet_network(bool is_ipv4, const char *cp,
|
||||||
|
bh_inet_network_output_t *out)
|
||||||
{
|
{
|
||||||
if (!cp)
|
if (!cp)
|
||||||
return BHT_ERROR;
|
return BHT_ERROR;
|
||||||
|
|
||||||
*out = inet_network(cp);
|
if (is_ipv4) {
|
||||||
|
if (inet_pton(AF_INET, cp, &out->ipv4) != 1) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
/* Note: ntohl(INADDR_NONE) == INADDR_NONE */
|
||||||
|
out->ipv4 = ntohl(out->ipv4);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return BHT_OK;
|
return BHT_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ extern "C" {
|
||||||
|
|
||||||
/* Address families. */
|
/* Address families. */
|
||||||
#define AF_INET 2 /* IP protocol family. */
|
#define AF_INET 2 /* IP protocol family. */
|
||||||
|
#define AF_INET6 10 /* IP version 6. */
|
||||||
|
|
||||||
/* Standard well-defined IP protocols. */
|
/* Standard well-defined IP protocols. */
|
||||||
#define IPPROTO_TCP 6 /* Transmission Control Protocol. */
|
#define IPPROTO_TCP 6 /* Transmission Control Protocol. */
|
||||||
|
@ -98,6 +99,12 @@ struct sockaddr {
|
||||||
uint32_t
|
uint32_t
|
||||||
ntohl(uint32_t value);
|
ntohl(uint32_t value);
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
htonl(uint32_t value);
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
htons(uint16_t value);
|
||||||
|
|
||||||
int
|
int
|
||||||
socket(int domain, int type, int protocol);
|
socket(int domain, int type, int protocol);
|
||||||
|
|
||||||
|
|
|
@ -37,17 +37,27 @@ deinit_winsock()
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
os_socket_create(bh_socket_t *sock, int tcp_or_udp)
|
os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp)
|
||||||
{
|
{
|
||||||
|
int af;
|
||||||
|
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
return BHT_ERROR;
|
return BHT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (1 == tcp_or_udp) {
|
if (is_ipv4) {
|
||||||
*sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
af = AF_INET;
|
||||||
}
|
}
|
||||||
else if (0 == tcp_or_udp) {
|
else {
|
||||||
*sock = socket(AF_INET, SOCK_DGRAM, 0);
|
errno = ENOSYS;
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_tcp) {
|
||||||
|
*sock = socket(af, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*sock = socket(af, SOCK_DGRAM, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (*sock == -1) ? BHT_ERROR : BHT_OK;
|
return (*sock == -1) ? BHT_ERROR : BHT_OK;
|
||||||
|
@ -154,12 +164,28 @@ os_socket_shutdown(bh_socket_t socket)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
os_socket_inet_network(const char *cp, uint32 *out)
|
os_socket_inet_network(bool is_ipv4, const char *cp,
|
||||||
|
bh_inet_network_output_t *out)
|
||||||
{
|
{
|
||||||
if (!cp)
|
if (!cp)
|
||||||
return BHT_ERROR;
|
return BHT_ERROR;
|
||||||
|
|
||||||
*out = inet_addr(cp);
|
if (is_ipv4) {
|
||||||
|
if (inet_pton(AF_INET, cp, &out->ipv4) != 1) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
/* Note: ntohl(INADDR_NONE) == INADDR_NONE */
|
||||||
|
out->ipv4 = ntohl(out->ipv4);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return BHT_OK;
|
return BHT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
*/
|
*/
|
||||||
|
#include "tcp_utils.h"
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
@ -14,28 +15,50 @@
|
||||||
#include <wasi_socket_ext.h>
|
#include <wasi_socket_ext.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_sockaddr_inet(struct sockaddr_in *addr)
|
||||||
|
{
|
||||||
|
/* 127.0.0.1:1234 */
|
||||||
|
addr->sin_family = AF_INET;
|
||||||
|
addr->sin_port = htons(1234);
|
||||||
|
addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_sockaddr_inet6(struct sockaddr_in6 *addr)
|
||||||
|
{
|
||||||
|
/* [::1]:1234 */
|
||||||
|
addr->sin6_family = AF_INET6;
|
||||||
|
addr->sin6_port = htons(1234);
|
||||||
|
addr->sin6_addr = in6addr_loopback;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int socket_fd, ret, total_size = 0;
|
int socket_fd, ret, total_size = 0, af;
|
||||||
char buffer[1024] = { 0 };
|
char buffer[1024] = { 0 };
|
||||||
char ip_string[16] = { 0 };
|
char ip_string[64] = { 0 };
|
||||||
struct sockaddr_in server_address = { 0 };
|
|
||||||
struct sockaddr_in local_address = { 0 };
|
|
||||||
socklen_t len;
|
socklen_t len;
|
||||||
|
struct sockaddr_storage server_address = { 0 };
|
||||||
|
struct sockaddr_storage local_address = { 0 };
|
||||||
|
|
||||||
|
if (argc > 1 && strcmp(argv[1], "inet6") == 0) {
|
||||||
|
af = AF_INET6;
|
||||||
|
init_sockaddr_inet6((struct sockaddr_in6 *)&server_address);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
af = AF_INET;
|
||||||
|
init_sockaddr_inet((struct sockaddr_in *)&server_address);
|
||||||
|
}
|
||||||
|
|
||||||
printf("[Client] Create socket\n");
|
printf("[Client] Create socket\n");
|
||||||
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
|
socket_fd = socket(af, SOCK_STREAM, 0);
|
||||||
if (socket_fd == -1) {
|
if (socket_fd == -1) {
|
||||||
perror("Create socket failed");
|
perror("Create socket failed");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 127.0.0.1:1234 */
|
|
||||||
server_address.sin_family = AF_INET;
|
|
||||||
server_address.sin_port = htons(1234);
|
|
||||||
server_address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
|
||||||
|
|
||||||
printf("[Client] Connect socket\n");
|
printf("[Client] Connect socket\n");
|
||||||
if (connect(socket_fd, (struct sockaddr *)&server_address,
|
if (connect(socket_fd, (struct sockaddr *)&server_address,
|
||||||
sizeof(server_address))
|
sizeof(server_address))
|
||||||
|
@ -53,11 +76,15 @@ main(int argc, char *argv[])
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
inet_ntop(AF_INET, &local_address.sin_addr, ip_string,
|
if (sockaddr_to_string((struct sockaddr *)&local_address, ip_string,
|
||||||
sizeof(ip_string) / sizeof(ip_string[0]));
|
sizeof(ip_string) / sizeof(ip_string[0]))
|
||||||
|
!= 0) {
|
||||||
|
printf("[Client] failed to parse local address\n");
|
||||||
|
close(socket_fd);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
printf("[Client] Local address is: %s:%d\n", ip_string,
|
printf("[Client] Local address is: %s\n", ip_string);
|
||||||
ntohs(local_address.sin_port));
|
|
||||||
|
|
||||||
printf("[Client] Client receive\n");
|
printf("[Client] Client receive\n");
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
*/
|
*/
|
||||||
|
#include "tcp_utils.h"
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
@ -41,28 +43,50 @@ run(void *arg)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_sockaddr_inet(struct sockaddr_in *addr)
|
||||||
|
{
|
||||||
|
/* 0.0.0.0:1234 */
|
||||||
|
addr->sin_family = AF_INET;
|
||||||
|
addr->sin_port = htons(1234);
|
||||||
|
addr->sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_sockaddr_inet6(struct sockaddr_in6 *addr)
|
||||||
|
{
|
||||||
|
/* [::]:1234 */
|
||||||
|
addr->sin6_family = AF_INET6;
|
||||||
|
addr->sin6_port = htons(1234);
|
||||||
|
addr->sin6_addr = in6addr_any;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int socket_fd = -1, addrlen = 0;
|
int socket_fd = -1, addrlen = 0, af;
|
||||||
struct sockaddr_in addr = { 0 };
|
struct sockaddr_storage addr = { 0 };
|
||||||
unsigned connections = 0;
|
unsigned connections = 0;
|
||||||
pthread_t workers[WORKER_NUM] = { 0 };
|
pthread_t workers[WORKER_NUM] = { 0 };
|
||||||
int client_sock_fds[WORKER_NUM] = { 0 };
|
int client_sock_fds[WORKER_NUM] = { 0 };
|
||||||
char ip_string[16];
|
char ip_string[64];
|
||||||
|
|
||||||
|
if (argc > 1 && strcmp(argv[1], "inet6") == 0) {
|
||||||
|
af = AF_INET6;
|
||||||
|
init_sockaddr_inet6((struct sockaddr_in6 *)&addr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
af = AF_INET;
|
||||||
|
init_sockaddr_inet((struct sockaddr_in *)&addr);
|
||||||
|
}
|
||||||
|
|
||||||
printf("[Server] Create socket\n");
|
printf("[Server] Create socket\n");
|
||||||
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
|
socket_fd = socket(af, SOCK_STREAM, 0);
|
||||||
if (socket_fd < 0) {
|
if (socket_fd < 0) {
|
||||||
perror("Create socket failed");
|
perror("Create socket failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 0.0.0.0:1234 */
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(1234);
|
|
||||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
|
|
||||||
printf("[Server] Bind socket\n");
|
printf("[Server] Bind socket\n");
|
||||||
addrlen = sizeof(addr);
|
addrlen = sizeof(addr);
|
||||||
if (bind(socket_fd, (struct sockaddr *)&addr, addrlen) < 0) {
|
if (bind(socket_fd, (struct sockaddr *)&addr, addrlen) < 0) {
|
||||||
|
@ -85,11 +109,14 @@ main(int argc, char *argv[])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
inet_ntop(AF_INET, &addr.sin_addr, ip_string,
|
if (sockaddr_to_string((struct sockaddr *)&addr, ip_string,
|
||||||
sizeof(ip_string) / sizeof(ip_string[0]));
|
sizeof(ip_string) / sizeof(ip_string[0]))
|
||||||
|
!= 0) {
|
||||||
|
printf("[Server] failed to parse client address\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
printf("[Server] Client connected (%s:%d)\n", ip_string,
|
printf("[Server] Client connected (%s)\n", ip_string);
|
||||||
ntohs(addr.sin_port));
|
|
||||||
if (pthread_create(&workers[connections], NULL, run,
|
if (pthread_create(&workers[connections], NULL, run,
|
||||||
&client_sock_fds[connections])) {
|
&client_sock_fds[connections])) {
|
||||||
perror("Create a worker thread failed");
|
perror("Create a worker thread failed");
|
||||||
|
|
48
samples/socket-api/wasm-src/tcp_utils.h
Normal file
48
samples/socket-api/wasm-src/tcp_utils.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Amazon.com Inc. or its affiliates. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TCP_UTILS_H
|
||||||
|
#define TCP_UTILS_H
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
sockaddr_to_string(struct sockaddr *addr, char *str, size_t len)
|
||||||
|
{
|
||||||
|
uint16_t port;
|
||||||
|
char ip_string[64];
|
||||||
|
void *addr_buf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
switch (addr->sa_family) {
|
||||||
|
case AF_INET:
|
||||||
|
{
|
||||||
|
struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
|
||||||
|
port = addr_in->sin_port;
|
||||||
|
addr_buf = &addr_in->sin_addr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AF_INET6:
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr;
|
||||||
|
port = addr_in6->sin6_port;
|
||||||
|
addr_buf = &addr_in6->sin6_addr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inet_ntop(addr->sa_family, addr_buf, ip_string,
|
||||||
|
sizeof(ip_string) / sizeof(ip_string[0]));
|
||||||
|
|
||||||
|
ret = snprintf(str, len, "%s:%d", ip_string, ntohs(port));
|
||||||
|
|
||||||
|
return ret > 0 && (size_t)ret < len ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* TCP_UTILS_H */
|
Loading…
Reference in New Issue
Block a user