Skip to content

Commit 65ef246

Browse files
authored
wasip3: Implement getaddrinfo (WebAssembly#764)
Include `netdb.c` in the build for wasip3 and update it to work with WASIp3. A small test is included which is mostly manually verified as it's not asserted whether getaddrinfo works or it doesn't due to the flaky nature of DNS.
1 parent 3727959 commit 65ef246

10 files changed

Lines changed: 167 additions & 27 deletions

File tree

cmake/bindings.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ add_custom_target(
132132
"--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.set-times"
133133
"--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-until"
134134
"--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-for"
135+
"--async=-wasi:sockets/ip-name-lookup@${wasip3-version}#resolve-addresses"
135136
${CMAKE_SOURCE_DIR}/wasi/p3/wit
136137
COMMAND cmake -E copy wasip3.h ${bottom_half}/headers/public/wasi/__generated_wasip3.h
137138
COMMAND cmake -E copy wasip3_component_type.o ${bottom_half}/sources

expected/wasm32-wasip3/defined-symbols.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,7 @@ fputws_unlocked
713713
fread
714714
fread_unlocked
715715
free
716+
freeaddrinfo
716717
freelocale
717718
freopen
718719
freopen64
@@ -752,6 +753,7 @@ get_avphys_pages
752753
get_nprocs
753754
get_nprocs_conf
754755
get_phys_pages
756+
getaddrinfo
755757
getc
756758
getc_unlocked
757759
getchar
@@ -763,16 +765,22 @@ getdelim
763765
getdomainname
764766
getentropy
765767
getenv
768+
gethostbyaddr
769+
gethostbyname
766770
gethostid
767771
gethostname
768772
getline
773+
getnameinfo
769774
getopt
770775
getopt_long
771776
getopt_long_only
772777
getpagesize
773778
getpeername
774779
getpid
780+
getprotobyname
775781
getrusage
782+
getservbyname
783+
getservbyport
776784
getsockname
777785
getsockopt
778786
getsubopt
@@ -788,12 +796,14 @@ globfree
788796
globfree64
789797
gmtime
790798
gmtime_r
799+
h_errno
791800
hcreate
792801
hcreate_r
793802
hdestroy
794803
hdestroy_r
795804
hsearch
796805
hsearch_r
806+
hstrerror
797807
htonl
798808
htons
799809
hypot

libc-bottom-half/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,12 @@ else()
149149
sources/sockopt.c
150150
sources/tcp.c
151151
sources/udp.c
152+
sources/netdb.c
152153
)
153154
endif()
154155

155156
if(WASI STREQUAL "p2")
156157
list(APPEND bottom_half_sources
157-
sources/netdb.c
158158
sources/wasip2.c
159159
sources/wasip2_stdio.c
160160
)

libc-bottom-half/headers/private/wasi/sockets_utils.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,19 @@
1111
typedef network_error_code_t sockets_error_code_t;
1212
typedef network_ip_address_family_t sockets_ip_address_family_t;
1313
typedef network_ip_socket_address_t sockets_ip_socket_address_t;
14+
typedef network_ip_socket_address_t sockets_ip_socket_address_t;
15+
typedef network_ip_address_t sockets_ip_address_t;
16+
typedef network_ipv4_address_t sockets_ipv4_address_t;
17+
typedef network_ipv6_address_t sockets_ipv6_address_t;
1418

1519
#define sockets_error_code_t network_error_code_t
1620
#define sockets_ip_address_family_t network_ip_address_family_t
1721
#define sockets_ip_socket_address_t network_ip_socket_address_t
1822

1923
#define SOCKETS_IP_ADDRESS_FAMILY_IPV4 NETWORK_IP_ADDRESS_FAMILY_IPV4
2024
#define SOCKETS_IP_ADDRESS_FAMILY_IPV6 NETWORK_IP_ADDRESS_FAMILY_IPV6
25+
#define SOCKETS_IP_ADDRESS_IPV4 NETWORK_IP_SOCKET_ADDRESS_IPV4
26+
#define SOCKETS_IP_ADDRESS_IPV6 NETWORK_IP_SOCKET_ADDRESS_IPV6
2127
#elif defined(__wasip3__)
2228
// already defines `sockets_*` types
2329
#else

libc-bottom-half/headers/public/wasi/__generated_wasip3.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libc-bottom-half/sources/netdb.c

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,48 +3,73 @@
33
#include <netdb.h>
44
#include <stdlib.h>
55
#include <string.h>
6+
#include <wasi/file_utils.h>
67
#include <wasi/sockets_utils.h>
78

89
#ifdef __wasip1__
910
static_assert(SOCK_DGRAM == __WASI_FILETYPE_SOCKET_DGRAM, "value mismatch");
1011
static_assert(SOCK_STREAM == __WASI_FILETYPE_SOCKET_STREAM, "value mismatch");
1112
#endif
1213

14+
#ifdef __wasip2__
15+
#define IP_NAME_LOOKUP_ERROR_CODE_NAME_UNRESOLVABLE \
16+
NETWORK_ERROR_CODE_NAME_UNRESOLVABLE
17+
#define IP_NAME_LOOKUP_ERROR_CODE_TEMPORARY_RESOLVER_FAILURE \
18+
NETWORK_ERROR_CODE_TEMPORARY_RESOLVER_FAILURE
19+
#define IP_NAME_LOOKUP_ERROR_CODE_PERMANENT_RESOLVER_FAILURE \
20+
NETWORK_ERROR_CODE_PERMANENT_RESOLVER_FAILURE
21+
#endif
22+
1323
_Thread_local int h_errno = 0;
1424

1525
static struct servent global_serv = {0};
1626

1727
static int map_error(ip_name_lookup_error_code_t error) {
1828
switch (error) {
29+
#ifdef __wasip2__
1930
case NETWORK_ERROR_CODE_OUT_OF_MEMORY:
2031
return EAI_MEMORY;
21-
case NETWORK_ERROR_CODE_NAME_UNRESOLVABLE:
32+
#endif
33+
case IP_NAME_LOOKUP_ERROR_CODE_NAME_UNRESOLVABLE:
2234
return EAI_NONAME;
23-
case NETWORK_ERROR_CODE_TEMPORARY_RESOLVER_FAILURE:
35+
case IP_NAME_LOOKUP_ERROR_CODE_TEMPORARY_RESOLVER_FAILURE:
2436
return EAI_AGAIN;
25-
case NETWORK_ERROR_CODE_PERMANENT_RESOLVER_FAILURE:
37+
case IP_NAME_LOOKUP_ERROR_CODE_PERMANENT_RESOLVER_FAILURE:
2638
return EAI_FAIL;
39+
#ifdef __wasip3__
40+
case IP_NAME_LOOKUP_ERROR_CODE_UNKNOWN:
41+
errno = EIO;
42+
return EAI_SYSTEM;
43+
case IP_NAME_LOOKUP_ERROR_CODE_ACCESS_DENIED:
44+
errno = EACCES;
45+
return EAI_SYSTEM;
46+
case IP_NAME_LOOKUP_ERROR_CODE_INVALID_ARGUMENT:
47+
errno = EINVAL;
48+
return EAI_SYSTEM;
49+
#endif
2750

2851
default:
52+
#ifdef __wasip2__
2953
__wasilibc_socket_error_to_errno(error);
54+
#endif
3055
return EAI_SYSTEM;
3156
}
3257
}
3358

34-
static int add_addr(ip_name_lookup_option_ip_address_t address, in_port_t port,
35-
int socktype, const struct addrinfo *restrict hint,
59+
static int add_addr(sockets_ip_address_t address, in_port_t port, int socktype,
60+
const struct addrinfo *restrict hint,
3661
struct addrinfo **restrict current,
3762
struct addrinfo **restrict res) {
3863
int family;
3964
struct sockaddr *addr;
4065
socklen_t addrlen;
41-
switch (address.val.tag) {
42-
case NETWORK_IP_ADDRESS_IPV4: {
66+
switch (address.tag) {
67+
case SOCKETS_IP_ADDRESS_IPV4: {
4368
if (hint && hint->ai_family != AF_UNSPEC && hint->ai_family != AF_INET) {
4469
return 0;
4570
}
4671

47-
network_ipv4_address_t ip = address.val.val.ipv4;
72+
sockets_ipv4_address_t ip = address.val.ipv4;
4873

4974
family = PF_INET;
5075
addrlen = sizeof(struct sockaddr_in);
@@ -63,12 +88,12 @@ static int add_addr(ip_name_lookup_option_ip_address_t address, in_port_t port,
6388
memcpy(addr, &sockaddr, addrlen);
6489
break;
6590
}
66-
case NETWORK_IP_ADDRESS_IPV6: {
91+
case SOCKETS_IP_ADDRESS_IPV6: {
6792
if (hint && hint->ai_family != AF_UNSPEC && hint->ai_family != AF_INET6) {
6893
return 0;
6994
}
7095

71-
network_ipv6_address_t ip = address.val.val.ipv6;
96+
sockets_ipv6_address_t ip = address.val.ipv6;
7297

7398
family = PF_INET6;
7499
addrlen = sizeof(struct sockaddr_in6);
@@ -171,16 +196,25 @@ int getaddrinfo(const char *restrict host, const char *restrict serv,
171196

172197
*res = NULL;
173198
struct addrinfo *current = NULL;
174-
wasip2_string_t name = {.ptr = (uint8_t *)host, .len = strlen(host)};
175-
ip_name_lookup_own_resolve_address_stream_t stream;
199+
wasi_string_t name = {.ptr = (uint8_t *)host, .len = strlen(host)};
176200
ip_name_lookup_error_code_t error;
201+
#ifdef __wasip2__
202+
ip_name_lookup_own_resolve_address_stream_t stream;
177203
if (!ip_name_lookup_resolve_addresses(__wasi_sockets_utils__borrow_network(),
178204
&name, &stream, &error))
179205
return map_error(error);
180-
181-
int ret = 0;
182206
ip_name_lookup_borrow_resolve_address_stream_t stream_borrow =
183207
ip_name_lookup_borrow_resolve_address_stream(stream);
208+
poll_own_pollable_t pollable;
209+
pollable.__handle = 0;
210+
#else
211+
ip_name_lookup_list_ip_address_t addresses;
212+
if (!ip_name_lookup_resolve_addresses(&name, &addresses, &error))
213+
return map_error(error);
214+
size_t next = 0;
215+
#endif
216+
217+
int ret = 0;
184218
// The 'serv' parameter can be either a port number or a service name.
185219
int port = 0;
186220
uint16_t protocol = SERVICE_PROTOCOL_TCP;
@@ -198,13 +232,11 @@ int getaddrinfo(const char *restrict host, const char *restrict serv,
198232
}
199233
}
200234

201-
poll_own_pollable_t pollable;
202-
pollable.__handle = 0;
203-
204235
while (ret == 0) {
205-
ip_name_lookup_option_ip_address_t address;
236+
#ifdef __wasip2__
237+
ip_name_lookup_option_ip_address_t maybe_address;
206238
if (!ip_name_lookup_method_resolve_address_stream_resolve_next_address(
207-
stream_borrow, &address, &error)) {
239+
stream_borrow, &maybe_address, &error)) {
208240
if (error != NETWORK_ERROR_CODE_WOULD_BLOCK) {
209241
freeaddrinfo(*res);
210242
ret = map_error(error);
@@ -218,8 +250,15 @@ int getaddrinfo(const char *restrict host, const char *restrict serv,
218250
poll_method_pollable_block(poll_borrow_pollable(pollable));
219251
continue;
220252
}
221-
if (!address.is_some)
253+
if (!maybe_address.is_some)
254+
break;
255+
sockets_ip_address_t address = maybe_address.val;
256+
257+
#else
258+
if (next == addresses.len)
222259
break;
260+
sockets_ip_address_t address = addresses.ptr[next++];
261+
#endif
223262
if (protocol & SERVICE_PROTOCOL_TCP) {
224263
ret = add_addr(address, htons(port), SOCK_STREAM, hint, &current, res);
225264
if (ret)
@@ -232,9 +271,13 @@ int getaddrinfo(const char *restrict host, const char *restrict serv,
232271
}
233272
}
234273

274+
#ifdef __wasip2__
235275
if (pollable.__handle != 0)
236276
poll_pollable_drop_own(pollable);
237277
ip_name_lookup_resolve_address_stream_drop_own(stream);
278+
#else
279+
ip_name_lookup_list_ip_address_free(&addresses);
280+
#endif
238281
return ret;
239282
}
240283

libc-bottom-half/sources/sockets_utils.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ typedef network_ipv4_socket_address_t sockets_ipv4_socket_address_t;
3737
typedef network_ipv4_address_t sockets_ipv4_address_t;
3838
typedef network_ipv6_socket_address_t sockets_ipv6_socket_address_t;
3939
typedef network_ipv6_address_t sockets_ipv6_address_t;
40-
typedef network_ip_socket_address_t sockets_ip_socket_address_t;
4140
#endif
4241

4342
static const service_entry_t global_services[] = {

libc-bottom-half/sources/wasip3.c

Lines changed: 27 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ function(register_test test_name executable_name)
135135
list(APPEND wasmtime_args --wasm component-model-async)
136136
list(APPEND wasmtime_args --wasi p3)
137137
endif()
138+
list(APPEND wasmtime_args --wasi allow-ip-name-lookup)
138139

139140
add_test(
140141
NAME "${test_name}"
@@ -339,6 +340,7 @@ if (NOT (WASI STREQUAL "p1"))
339340
add_wasilibc_test(sockets-nonblocking-udp-multiple.c NETWORK FAILP3)
340341
add_wasilibc_test(sockets-fcntl.c NETWORK)
341342
add_wasilibc_test(sockets-udp-connected.c NETWORK FAILP3)
343+
add_wasilibc_test(getaddrinfo.c NETWORK)
342344

343345
# TODO: flaky tests
344346
# add_wasilibc_test(sockets-nonblocking.c NETWORK)

0 commit comments

Comments
 (0)