mirror of
https://git.proxmox.com/git/wasi-libc
synced 2025-07-27 12:52:53 +00:00
implement getsockname
, getpeername
, and getaddrinfo
(#488)
This also includes stubs for `gethostbyname`, `gethostbyaddr`, etc. which were necessary to get CPython to build. I believe it will be possible to implement them all properly at some point, but don't have the bandwidth at the moment. Finally, this includes a few fixes for issues I missed in earlier PRs that surfaced when running the CPython `asyncio` test suite. Signed-off-by: Joel Dice <joel.dice@fermyon.com> Co-authored-by: Dave Bakker <github@davebakker.io>
This commit is contained in:
parent
1ab654e2f5
commit
d038294899
20
Makefile
20
Makefile
@ -94,7 +94,9 @@ LIBC_BOTTOM_HALF_OMIT_SOURCES := \
|
||||
$(LIBC_BOTTOM_HALF_SOURCES)/accept-wasip2.c \
|
||||
$(LIBC_BOTTOM_HALF_SOURCES)/shutdown.c \
|
||||
$(LIBC_BOTTOM_HALF_SOURCES)/sockopt.c \
|
||||
$(LIBC_BOTTOM_HALF_SOURCES)/poll-wasip2.c
|
||||
$(LIBC_BOTTOM_HALF_SOURCES)/poll-wasip2.c \
|
||||
$(LIBC_BOTTOM_HALF_SOURCES)/getsockpeername.c \
|
||||
$(LIBC_BOTTOM_HALF_SOURCES)/netdb.c
|
||||
LIBC_BOTTOM_HALF_ALL_SOURCES := $(filter-out $(LIBC_BOTTOM_HALF_OMIT_SOURCES),$(LIBC_BOTTOM_HALF_ALL_SOURCES))
|
||||
# Omit p2-specific headers from include-all.c test.
|
||||
# for exception-handling.
|
||||
@ -249,6 +251,13 @@ LIBC_TOP_HALF_MUSL_SOURCES = \
|
||||
$(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/complex/*.c)) \
|
||||
$(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/crypt/*.c)
|
||||
|
||||
ifeq ($(WASI_SNAPSHOT), p2)
|
||||
LIBC_TOP_HALF_MUSL_SOURCES += \
|
||||
$(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \
|
||||
network/gai_strerror.c \
|
||||
)
|
||||
endif
|
||||
|
||||
ifeq ($(THREAD_MODEL), posix)
|
||||
LIBC_TOP_HALF_MUSL_SOURCES += \
|
||||
$(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \
|
||||
@ -387,6 +396,10 @@ ASMFLAGS += -matomics
|
||||
CFLAGS += -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)
|
||||
endif
|
||||
|
||||
ifeq ($(WASI_SNAPSHOT), p2)
|
||||
EXTRA_CFLAGS += -D__wasilibc_use_wasip2
|
||||
endif
|
||||
|
||||
# Expose the public headers to the implementation. We use `-isystem` for
|
||||
# purpose for two reasons:
|
||||
#
|
||||
@ -500,7 +513,6 @@ MUSL_OMIT_HEADERS += \
|
||||
"sys/auxv.h" \
|
||||
"pwd.h" "shadow.h" "grp.h" \
|
||||
"mntent.h" \
|
||||
"netdb.h" \
|
||||
"resolv.h" \
|
||||
"pty.h" \
|
||||
"ulimit.h" \
|
||||
@ -523,6 +535,10 @@ MUSL_OMIT_HEADERS += \
|
||||
"sys/sysmacros.h" \
|
||||
"aio.h"
|
||||
|
||||
ifeq ($(WASI_SNAPSHOT), p1)
|
||||
MUSL_OMIT_HEADERS += "netdb.h"
|
||||
endif
|
||||
|
||||
ifeq ($(THREAD_MODEL), single)
|
||||
# Remove headers not supported in single-threaded mode.
|
||||
MUSL_OMIT_HEADERS += "pthread.h"
|
||||
|
@ -535,6 +535,9 @@ dprintf
|
||||
drand48
|
||||
drem
|
||||
dremf
|
||||
drop_tcp_socket
|
||||
drop_udp_socket
|
||||
drop_udp_socket_streams
|
||||
duplocale
|
||||
ecvt
|
||||
encrypt
|
||||
@ -709,6 +712,7 @@ fputws_unlocked
|
||||
fread
|
||||
fread_unlocked
|
||||
free
|
||||
freeaddrinfo
|
||||
freelocale
|
||||
freopen
|
||||
freopen64
|
||||
@ -737,11 +741,13 @@ fwprintf
|
||||
fwrite
|
||||
fwrite_unlocked
|
||||
fwscanf
|
||||
gai_strerror
|
||||
gcvt
|
||||
get_avphys_pages
|
||||
get_nprocs
|
||||
get_nprocs_conf
|
||||
get_phys_pages
|
||||
getaddrinfo
|
||||
getc
|
||||
getc_unlocked
|
||||
getchar
|
||||
@ -753,14 +759,22 @@ getdelim
|
||||
getdomainname
|
||||
getentropy
|
||||
getenv
|
||||
gethostbyaddr
|
||||
gethostbyname
|
||||
gethostid
|
||||
getline
|
||||
getnameinfo
|
||||
getopt
|
||||
getopt_long
|
||||
getopt_long_only
|
||||
getpagesize
|
||||
getpeername
|
||||
getpid
|
||||
getprotobyname
|
||||
getrusage
|
||||
getservbyname
|
||||
getservbyport
|
||||
getsockname
|
||||
getsockopt
|
||||
getsubopt
|
||||
gettimeofday
|
||||
@ -775,12 +789,14 @@ globfree
|
||||
globfree64
|
||||
gmtime
|
||||
gmtime_r
|
||||
h_errno
|
||||
hcreate
|
||||
hcreate_r
|
||||
hdestroy
|
||||
hdestroy_r
|
||||
hsearch
|
||||
hsearch_r
|
||||
hstrerror
|
||||
htonl
|
||||
htons
|
||||
hypot
|
||||
@ -1246,6 +1262,8 @@ tcp_bind
|
||||
tcp_borrow_tcp_socket
|
||||
tcp_create_socket_create_tcp_socket
|
||||
tcp_create_socket_result_own_tcp_socket_error_code_free
|
||||
tcp_getpeername
|
||||
tcp_getsockname
|
||||
tcp_getsockopt
|
||||
tcp_ip_socket_address_free
|
||||
tcp_listen
|
||||
@ -1338,6 +1356,8 @@ udp_borrow_outgoing_datagram_stream
|
||||
udp_borrow_udp_socket
|
||||
udp_create_socket_create_udp_socket
|
||||
udp_create_socket_result_own_udp_socket_error_code_free
|
||||
udp_getpeername
|
||||
udp_getsockname
|
||||
udp_getsockopt
|
||||
udp_incoming_datagram_free
|
||||
udp_incoming_datagram_stream_drop_borrow
|
||||
|
@ -102,6 +102,7 @@
|
||||
#include <memory.h>
|
||||
#include <monetary.h>
|
||||
#include <mqueue.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/igmp.h>
|
||||
#include <netinet/in.h>
|
||||
|
@ -37,6 +37,13 @@
|
||||
#define AF_INET6 PF_INET6
|
||||
#define AF_UNIX 3
|
||||
#define AF_UNSPEC PF_UNSPEC
|
||||
#define AI_ADDRCONFIG 0x20
|
||||
#define AI_ALL 0x10
|
||||
#define AI_CANONNAME 0x02
|
||||
#define AI_NUMERICHOST 0x04
|
||||
#define AI_NUMERICSERV 0x400
|
||||
#define AI_PASSIVE 0x01
|
||||
#define AI_V4MAPPED 0x08
|
||||
#define ALT_DIGITS 0x2002F
|
||||
#define AM_STR 0x20026
|
||||
#define ANYMARK 0x01
|
||||
@ -192,6 +199,24 @@
|
||||
#define EADDRNOTAVAIL __WASI_ERRNO_ADDRNOTAVAIL
|
||||
#define EAFNOSUPPORT __WASI_ERRNO_AFNOSUPPORT
|
||||
#define EAGAIN __WASI_ERRNO_AGAIN
|
||||
#define EAI_ADDRFAMILY -9
|
||||
#define EAI_AGAIN -3
|
||||
#define EAI_ALLDONE -103
|
||||
#define EAI_BADFLAGS -1
|
||||
#define EAI_CANCELED -101
|
||||
#define EAI_FAIL -4
|
||||
#define EAI_FAMILY -6
|
||||
#define EAI_IDN_ENCODE -105
|
||||
#define EAI_INPROGRESS -100
|
||||
#define EAI_INTR -104
|
||||
#define EAI_MEMORY -10
|
||||
#define EAI_NODATA -5
|
||||
#define EAI_NONAME -2
|
||||
#define EAI_NOTCANCELED -102
|
||||
#define EAI_OVERFLOW -12
|
||||
#define EAI_SERVICE -8
|
||||
#define EAI_SOCKTYPE -7
|
||||
#define EAI_SYSTEM -11
|
||||
#define EALREADY __WASI_ERRNO_ALREADY
|
||||
#define EBADF __WASI_ERRNO_BADF
|
||||
#define EBADID 5
|
||||
@ -489,6 +514,7 @@
|
||||
#define HIBITL MINLONG
|
||||
#define HIBITS MINSHORT
|
||||
#define HOST_NAME_MAX 255
|
||||
#define HOST_NOT_FOUND 1
|
||||
#define HUGE 3.40282346638528859812e+38F
|
||||
#define HUGE_VAL ((double)INFINITY)
|
||||
#define HUGE_VALF INFINITY
|
||||
@ -1239,6 +1265,14 @@
|
||||
#define NEW_ENV_VAR 0
|
||||
#define NGROUPS 32
|
||||
#define NGROUPS_MAX 32
|
||||
#define NI_DGRAM 0x10
|
||||
#define NI_MAXHOST 255
|
||||
#define NI_MAXSERV 32
|
||||
#define NI_NAMEREQD 0x08
|
||||
#define NI_NOFQDN 0x04
|
||||
#define NI_NUMERICHOST 0x01
|
||||
#define NI_NUMERICSCOPE 0x100
|
||||
#define NI_NUMERICSERV 0x02
|
||||
#define NL_ARGMAX 9
|
||||
#define NL_CAT_LOCALE 1
|
||||
#define NL_LANGMAX 32
|
||||
@ -1257,6 +1291,9 @@
|
||||
#define NOTAUTH ns_r_notauth
|
||||
#define NOTIMP ns_r_notimpl
|
||||
#define NOTZONE ns_r_notzone
|
||||
#define NO_ADDRESS NO_DATA
|
||||
#define NO_DATA 4
|
||||
#define NO_RECOVERY 3
|
||||
#define NR_ICMP_TYPES 18
|
||||
#define NR_ICMP_UNREACH 15
|
||||
#define NSLC 18
|
||||
@ -1968,6 +2005,7 @@
|
||||
#define TOREAD 00004
|
||||
#define TOWRITE 00002
|
||||
#define TRANSIENT 4
|
||||
#define TRY_AGAIN 2
|
||||
#define TSGID 02000
|
||||
#define TSS_DTOR_ITERATIONS 4
|
||||
#define TSUID 04000
|
||||
@ -2173,6 +2211,7 @@
|
||||
#define _MATH_H
|
||||
#define _MONETARY_H
|
||||
#define _MQUEUE_H
|
||||
#define _NETDB_H
|
||||
#define _NETINET_ICMP6_H
|
||||
#define _NETINET_IGMP_H
|
||||
#define _NETINET_IN_H
|
||||
@ -3194,7 +3233,7 @@
|
||||
#define __wasilibc___typedef_suseconds_t_h
|
||||
#define __wasilibc___typedef_time_t_h
|
||||
#define __wasilibc___typedef_uid_t_h
|
||||
#define __wasilibc_use_wasip2
|
||||
#define __wasilibc_use_wasip2 1
|
||||
#define __wasm 1
|
||||
#define __wasm32 1
|
||||
#define __wasm32__ 1
|
||||
@ -3281,6 +3320,8 @@
|
||||
#define glob64 glob
|
||||
#define glob64_t glob_t
|
||||
#define globfree64 globfree
|
||||
#define h_addr h_addr_list[0]
|
||||
#define h_errno h_errno
|
||||
#define howmany(n,d) (((n)+((d)-1))/(d))
|
||||
#define htobe16(x) __bswap16(x)
|
||||
#define htobe32(x) __bswap32(x)
|
||||
|
229
libc-bottom-half/sources/getsockpeername.c
Normal file
229
libc-bottom-half/sources/getsockpeername.c
Normal file
@ -0,0 +1,229 @@
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <wasi/descriptor_table.h>
|
||||
#include <wasi/sockets_utils.h>
|
||||
|
||||
int tcp_getsockname(tcp_socket_t *socket, struct sockaddr *addr,
|
||||
socklen_t *addrlen)
|
||||
{
|
||||
output_sockaddr_t output_addr;
|
||||
if (!__wasi_sockets_utils__output_addr_validate(
|
||||
socket->family, addr, addrlen, &output_addr)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (output_addr.tag == OUTPUT_SOCKADDR_NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (socket->state.tag) {
|
||||
case TCP_SOCKET_STATE_UNBOUND:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
|
||||
case TCP_SOCKET_STATE_BOUND:
|
||||
case TCP_SOCKET_STATE_CONNECTING:
|
||||
case TCP_SOCKET_STATE_CONNECT_FAILED:
|
||||
case TCP_SOCKET_STATE_LISTENING:
|
||||
case TCP_SOCKET_STATE_CONNECTED:
|
||||
// OK. Continue..
|
||||
break;
|
||||
|
||||
default: /* unreachable */
|
||||
abort();
|
||||
}
|
||||
|
||||
network_error_code_t error;
|
||||
network_ip_socket_address_t result;
|
||||
tcp_borrow_tcp_socket_t socket_borrow =
|
||||
tcp_borrow_tcp_socket(socket->socket);
|
||||
if (!tcp_method_tcp_socket_local_address(socket_borrow, &result,
|
||||
&error)) {
|
||||
errno = __wasi_sockets_utils__map_error(error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
__wasi_sockets_utils__output_addr_write(result, &output_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tcp_getpeername(tcp_socket_t *socket, struct sockaddr *addr,
|
||||
socklen_t *addrlen)
|
||||
{
|
||||
output_sockaddr_t output_addr;
|
||||
if (!__wasi_sockets_utils__output_addr_validate(
|
||||
socket->family, addr, addrlen, &output_addr)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (output_addr.tag == OUTPUT_SOCKADDR_NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (socket->state.tag) {
|
||||
case TCP_SOCKET_STATE_UNBOUND:
|
||||
case TCP_SOCKET_STATE_BOUND:
|
||||
case TCP_SOCKET_STATE_CONNECTING:
|
||||
case TCP_SOCKET_STATE_CONNECT_FAILED:
|
||||
case TCP_SOCKET_STATE_LISTENING:
|
||||
errno = ENOTCONN;
|
||||
return -1;
|
||||
|
||||
case TCP_SOCKET_STATE_CONNECTED:
|
||||
// OK. Continue..
|
||||
break;
|
||||
|
||||
default: /* unreachable */
|
||||
abort();
|
||||
}
|
||||
|
||||
network_error_code_t error;
|
||||
network_ip_socket_address_t result;
|
||||
tcp_borrow_tcp_socket_t socket_borrow =
|
||||
tcp_borrow_tcp_socket(socket->socket);
|
||||
if (!tcp_method_tcp_socket_remote_address(socket_borrow, &result,
|
||||
&error)) {
|
||||
errno = __wasi_sockets_utils__map_error(error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
__wasi_sockets_utils__output_addr_write(result, &output_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int udp_getsockname(udp_socket_t *socket, struct sockaddr *addr,
|
||||
socklen_t *addrlen)
|
||||
{
|
||||
output_sockaddr_t output_addr;
|
||||
if (!__wasi_sockets_utils__output_addr_validate(
|
||||
socket->family, addr, addrlen, &output_addr)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (output_addr.tag == OUTPUT_SOCKADDR_NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (socket->state.tag) {
|
||||
case UDP_SOCKET_STATE_UNBOUND:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
|
||||
case UDP_SOCKET_STATE_BOUND_NOSTREAMS:
|
||||
case UDP_SOCKET_STATE_BOUND_STREAMING:
|
||||
case UDP_SOCKET_STATE_CONNECTED:
|
||||
// OK. Continue..
|
||||
break;
|
||||
|
||||
default: /* unreachable */
|
||||
abort();
|
||||
}
|
||||
|
||||
network_error_code_t error;
|
||||
network_ip_socket_address_t result;
|
||||
udp_borrow_udp_socket_t socket_borrow =
|
||||
udp_borrow_udp_socket(socket->socket);
|
||||
if (!udp_method_udp_socket_local_address(socket_borrow, &result,
|
||||
&error)) {
|
||||
errno = __wasi_sockets_utils__map_error(error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
__wasi_sockets_utils__output_addr_write(result, &output_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int udp_getpeername(udp_socket_t *socket, struct sockaddr *addr,
|
||||
socklen_t *addrlen)
|
||||
{
|
||||
output_sockaddr_t output_addr;
|
||||
if (!__wasi_sockets_utils__output_addr_validate(
|
||||
socket->family, addr, addrlen, &output_addr)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (output_addr.tag == OUTPUT_SOCKADDR_NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (socket->state.tag) {
|
||||
case UDP_SOCKET_STATE_UNBOUND:
|
||||
case UDP_SOCKET_STATE_BOUND_NOSTREAMS:
|
||||
case UDP_SOCKET_STATE_BOUND_STREAMING:
|
||||
errno = ENOTCONN;
|
||||
return -1;
|
||||
|
||||
case UDP_SOCKET_STATE_CONNECTED:
|
||||
// OK. Continue..
|
||||
break;
|
||||
|
||||
default: /* unreachable */
|
||||
abort();
|
||||
}
|
||||
|
||||
network_error_code_t error;
|
||||
network_ip_socket_address_t result;
|
||||
udp_borrow_udp_socket_t socket_borrow =
|
||||
udp_borrow_udp_socket(socket->socket);
|
||||
if (!udp_method_udp_socket_remote_address(socket_borrow, &result,
|
||||
&error)) {
|
||||
errno = __wasi_sockets_utils__map_error(error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
__wasi_sockets_utils__output_addr_write(result, &output_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getsockname(int socket, struct sockaddr *__restrict addr,
|
||||
socklen_t *__restrict addrlen)
|
||||
{
|
||||
descriptor_table_entry_t *entry;
|
||||
if (!descriptor_table_get_ref(socket, &entry)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (entry->tag) {
|
||||
case DESCRIPTOR_TABLE_ENTRY_TCP_SOCKET:
|
||||
return tcp_getsockname(&entry->tcp_socket, addr, addrlen);
|
||||
case DESCRIPTOR_TABLE_ENTRY_UDP_SOCKET:
|
||||
return udp_getsockname(&entry->udp_socket, addr, addrlen);
|
||||
default:
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int getpeername(int socket, struct sockaddr *__restrict addr,
|
||||
socklen_t *__restrict addrlen)
|
||||
{
|
||||
descriptor_table_entry_t *entry;
|
||||
if (!descriptor_table_get_ref(socket, &entry)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (entry->tag) {
|
||||
case DESCRIPTOR_TABLE_ENTRY_TCP_SOCKET:
|
||||
return tcp_getpeername(&entry->tcp_socket, addr, addrlen);
|
||||
case DESCRIPTOR_TABLE_ENTRY_UDP_SOCKET:
|
||||
return udp_getpeername(&entry->udp_socket, addr, addrlen);
|
||||
default:
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
||||
}
|
238
libc-bottom-half/sources/netdb.c
Normal file
238
libc-bottom-half/sources/netdb.c
Normal file
@ -0,0 +1,238 @@
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <wasi/sockets_utils.h>
|
||||
|
||||
_Thread_local int h_errno = 0;
|
||||
|
||||
static int map_error(ip_name_lookup_error_code_t error)
|
||||
{
|
||||
switch (error) {
|
||||
case NETWORK_ERROR_CODE_OUT_OF_MEMORY:
|
||||
return EAI_MEMORY;
|
||||
case NETWORK_ERROR_CODE_NAME_UNRESOLVABLE:
|
||||
return EAI_NONAME;
|
||||
case NETWORK_ERROR_CODE_TEMPORARY_RESOLVER_FAILURE:
|
||||
return EAI_AGAIN;
|
||||
case NETWORK_ERROR_CODE_PERMANENT_RESOLVER_FAILURE:
|
||||
return EAI_FAIL;
|
||||
|
||||
default:
|
||||
errno = __wasi_sockets_utils__map_error(error);
|
||||
return EAI_SYSTEM;
|
||||
}
|
||||
}
|
||||
|
||||
static int add_addr(ip_name_lookup_option_ip_address_t address,
|
||||
const struct addrinfo *restrict hint,
|
||||
struct addrinfo **restrict current,
|
||||
struct addrinfo **restrict res)
|
||||
{
|
||||
int family;
|
||||
struct sockaddr *addr;
|
||||
socklen_t addrlen;
|
||||
switch (address.val.tag) {
|
||||
case NETWORK_IP_ADDRESS_IPV4: {
|
||||
if (hint && hint->ai_family != AF_UNSPEC &&
|
||||
hint->ai_family != AF_INET) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
network_ipv4_address_t ip = address.val.val.ipv4;
|
||||
|
||||
family = PF_INET;
|
||||
addrlen = sizeof(struct sockaddr_in);
|
||||
addr = malloc(addrlen);
|
||||
if (addr == NULL) {
|
||||
freeaddrinfo(*res);
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
|
||||
struct sockaddr_in sockaddr = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = 0,
|
||||
.sin_addr = { .s_addr = ip.f0 | (ip.f1 << 8) |
|
||||
(ip.f2 << 16) | (ip.f3 << 24) },
|
||||
};
|
||||
memcpy(addr, &sockaddr, addrlen);
|
||||
break;
|
||||
}
|
||||
case NETWORK_IP_ADDRESS_IPV6: {
|
||||
if (hint && hint->ai_family != AF_UNSPEC &&
|
||||
hint->ai_family != AF_INET6) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
network_ipv6_address_t ip = address.val.val.ipv6;
|
||||
|
||||
family = PF_INET6;
|
||||
addrlen = sizeof(struct sockaddr_in6);
|
||||
addr = malloc(addrlen);
|
||||
if (addr == NULL) {
|
||||
freeaddrinfo(*res);
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
|
||||
struct sockaddr_in6 sockaddr = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_port = 0,
|
||||
.sin6_addr = {
|
||||
.s6_addr = {
|
||||
ip.f0 >> 8,
|
||||
ip.f0 & 0xFF,
|
||||
ip.f1 >> 8,
|
||||
ip.f1 & 0xFF,
|
||||
ip.f2 >> 8,
|
||||
ip.f2 & 0xFF,
|
||||
ip.f3 >> 8,
|
||||
ip.f3 & 0xFF,
|
||||
ip.f4 >> 8,
|
||||
ip.f4 & 0xFF,
|
||||
ip.f5 >> 8,
|
||||
ip.f5 & 0xFF,
|
||||
ip.f6 >> 8,
|
||||
ip.f6 & 0xFF,
|
||||
ip.f7 >> 8,
|
||||
ip.f7 & 0xFF,
|
||||
} },
|
||||
.sin6_flowinfo = 0,
|
||||
.sin6_scope_id = 0,
|
||||
};
|
||||
memcpy(addr, &sockaddr, addrlen);
|
||||
break;
|
||||
}
|
||||
default: /* unreachable */
|
||||
abort();
|
||||
}
|
||||
|
||||
struct addrinfo *result = malloc(sizeof(struct addrinfo));
|
||||
if (result == NULL) {
|
||||
freeaddrinfo(*res);
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
|
||||
*result = (struct addrinfo){
|
||||
.ai_family = family,
|
||||
.ai_flags = 0,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_protocol = 0,
|
||||
.ai_addrlen = addrlen,
|
||||
.ai_addr = addr,
|
||||
.ai_canonname = NULL,
|
||||
.ai_next = NULL,
|
||||
};
|
||||
|
||||
if (*current) {
|
||||
(*current)->ai_next = result;
|
||||
*current = result;
|
||||
} else {
|
||||
*current = result;
|
||||
*res = result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getaddrinfo(const char *restrict host, const char *restrict serv,
|
||||
const struct addrinfo *restrict hint,
|
||||
struct addrinfo **restrict res)
|
||||
{
|
||||
if (host == NULL) {
|
||||
host = "localhost";
|
||||
}
|
||||
|
||||
*res = NULL;
|
||||
struct addrinfo *current = NULL;
|
||||
wasip2_string_t name = { .ptr = (uint8_t *)host, .len = strlen(host) };
|
||||
ip_name_lookup_own_resolve_address_stream_t stream;
|
||||
ip_name_lookup_error_code_t error;
|
||||
if (ip_name_lookup_resolve_addresses(
|
||||
__wasi_sockets_utils__borrow_network(), &name, &stream,
|
||||
&error)) {
|
||||
ip_name_lookup_borrow_resolve_address_stream_t stream_borrow =
|
||||
ip_name_lookup_borrow_resolve_address_stream(stream);
|
||||
while (true) {
|
||||
ip_name_lookup_option_ip_address_t address;
|
||||
if (ip_name_lookup_method_resolve_address_stream_resolve_next_address(
|
||||
stream_borrow, &address, &error)) {
|
||||
if (address.is_some) {
|
||||
int error = add_addr(address, hint,
|
||||
¤t, res);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if (error == NETWORK_ERROR_CODE_WOULD_BLOCK) {
|
||||
ip_name_lookup_own_pollable_t pollable =
|
||||
ip_name_lookup_method_resolve_address_stream_subscribe(
|
||||
stream_borrow);
|
||||
poll_borrow_pollable_t pollable_borrow =
|
||||
poll_borrow_pollable(pollable);
|
||||
poll_method_pollable_block(pollable_borrow);
|
||||
poll_pollable_drop_own(pollable);
|
||||
} else {
|
||||
freeaddrinfo(*res);
|
||||
return map_error(error);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return map_error(error);
|
||||
}
|
||||
}
|
||||
|
||||
void freeaddrinfo(struct addrinfo *p)
|
||||
{
|
||||
while (p) {
|
||||
struct addrinfo *next = p->ai_next;
|
||||
free(p->ai_addr);
|
||||
free(p);
|
||||
p = next;
|
||||
}
|
||||
}
|
||||
|
||||
int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,
|
||||
char *restrict host, socklen_t hostlen, char *restrict serv,
|
||||
socklen_t servlen, int flags)
|
||||
{
|
||||
// TODO wasi-sockets
|
||||
abort();
|
||||
}
|
||||
|
||||
struct hostent *gethostbyname(const char *name)
|
||||
{
|
||||
// TODO wasi-sockets
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type)
|
||||
{
|
||||
// TODO wasi-sockets
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *hstrerror(int err)
|
||||
{
|
||||
// TODO wasi-sockets
|
||||
return "hstrerror: TODO";
|
||||
}
|
||||
|
||||
struct servent *getservbyname(const char *name, const char *proto)
|
||||
{
|
||||
// TODO wasi-sockets
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct servent *getservbyport(int port, const char *proto)
|
||||
{
|
||||
// TODO wasi-sockets
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct protoent *getprotobyname(const char *name)
|
||||
{
|
||||
// TODO wasi-sockets
|
||||
return NULL;
|
||||
}
|
@ -118,8 +118,13 @@ struct hostent *gethostbyaddr (const void *, socklen_t, int);
|
||||
#ifdef __GNUC__
|
||||
__attribute__((const))
|
||||
#endif
|
||||
#ifdef __wasilibc_unmodified_upstream
|
||||
int *__h_errno_location(void);
|
||||
#define h_errno (*__h_errno_location())
|
||||
#elif (defined __wasilibc_use_wasip2)
|
||||
extern _Thread_local int h_errno;
|
||||
#define h_errno h_errno
|
||||
#endif
|
||||
#define HOST_NOT_FOUND 1
|
||||
#define TRY_AGAIN 2
|
||||
#define NO_RECOVERY 3
|
||||
|
@ -417,7 +417,7 @@ int listen (int, int);
|
||||
int accept (int, struct sockaddr *__restrict, socklen_t *__restrict);
|
||||
int accept4(int, struct sockaddr *__restrict, socklen_t *__restrict, int);
|
||||
|
||||
#ifdef __wasilibc_unmodified_upstream /* WASI has no getsockname/getpeername */
|
||||
#if (defined __wasilibc_unmodified_upstream) || (defined __wasilibc_use_wasip2)
|
||||
int getsockname (int, struct sockaddr *__restrict, socklen_t *__restrict);
|
||||
int getpeername (int, struct sockaddr *__restrict, socklen_t *__restrict);
|
||||
#endif
|
||||
@ -434,7 +434,7 @@ ssize_t recvmsg (int, struct msghdr *, int);
|
||||
#endif
|
||||
|
||||
int getsockopt (int, int, int, void *__restrict, socklen_t *__restrict);
|
||||
#ifdef __wasilibc_unmodified_upstream /* WASI has no setsockopt */
|
||||
#if (defined __wasilibc_unmodified_upstream) || (defined __wasilibc_use_wasip2)
|
||||
int setsockopt (int, int, int, const void *, socklen_t);
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user