Skip to content

Commit 7e923e7

Browse files
authored
wasip2: Refactor getaddrinfo implementation (WebAssembly#677)
* Use less indentation to make it a bit more readable * Cache the `pollable` across addreses * Restructure to use less indentation, e.g. handling an error in one level of indentation and the success case at one less level of indentation. * Close the `resolve-address-stream` resource when the function is finished or if an error is encountered.
1 parent 1d69d5f commit 7e923e7

File tree

1 file changed

+72
-67
lines changed

1 file changed

+72
-67
lines changed

libc-bottom-half/sources/netdb.c

Lines changed: 72 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -166,74 +166,79 @@ int getaddrinfo(const char *restrict host, const char *restrict serv,
166166
const struct addrinfo *restrict hint,
167167
struct addrinfo **restrict res)
168168
{
169-
if (host == NULL) {
170-
host = "localhost";
171-
}
169+
if (host == NULL) {
170+
host = "localhost";
171+
}
172172

173-
*res = NULL;
174-
struct addrinfo *current = NULL;
175-
wasip2_string_t name = { .ptr = (uint8_t *)host, .len = strlen(host) };
176-
ip_name_lookup_own_resolve_address_stream_t stream;
177-
ip_name_lookup_error_code_t error;
178-
if (ip_name_lookup_resolve_addresses(
179-
__wasi_sockets_utils__borrow_network(), &name, &stream,
180-
&error)) {
181-
ip_name_lookup_borrow_resolve_address_stream_t stream_borrow =
182-
ip_name_lookup_borrow_resolve_address_stream(stream);
183-
// The 'serv' parameter can be either a port number or a service name.
184-
int port = 0;
185-
uint16_t protocol = SERVICE_PROTOCOL_TCP;
186-
if (serv != NULL) {
187-
port = __wasi_sockets_utils__parse_port(serv);
188-
if (port < 0) {
189-
const service_entry_t *service = __wasi_sockets_utils__get_service_entry_by_name(serv);
190-
if (service) {
191-
port = service->port;
192-
protocol = service->protocol;
193-
}
194-
else {
195-
return EAI_NONAME;
196-
}
197-
}
198-
}
199-
while (true) {
200-
ip_name_lookup_option_ip_address_t address;
201-
if (ip_name_lookup_method_resolve_address_stream_resolve_next_address(
202-
stream_borrow, &address, &error)) {
203-
if (address.is_some) {
204-
if (protocol & SERVICE_PROTOCOL_TCP) {
205-
int error = add_addr(address, htons(port), SOCK_STREAM,
206-
hint, &current, res);
207-
if (error) {
208-
return error;
209-
}
210-
}
211-
if (protocol & SERVICE_PROTOCOL_UDP) {
212-
int error = add_addr(address, htons(port), SOCK_DGRAM,
213-
hint, &current, res);
214-
if (error) {
215-
return error;
216-
}
217-
}
218-
} else {
219-
return 0;
220-
}
221-
} else if (error == NETWORK_ERROR_CODE_WOULD_BLOCK) {
222-
ip_name_lookup_own_pollable_t pollable =
223-
ip_name_lookup_method_resolve_address_stream_subscribe(
224-
stream_borrow);
225-
poll_borrow_pollable_t pollable_borrow =
226-
poll_borrow_pollable(pollable);
227-
poll_method_pollable_block(pollable_borrow);
228-
poll_pollable_drop_own(pollable);
229-
} else {
230-
freeaddrinfo(*res);
231-
return map_error(error);
232-
}
233-
}
234-
} else {
235-
return map_error(error);
236-
}
173+
*res = NULL;
174+
struct addrinfo *current = NULL;
175+
wasip2_string_t name = { .ptr = (uint8_t *)host, .len = strlen(host) };
176+
ip_name_lookup_own_resolve_address_stream_t stream;
177+
ip_name_lookup_error_code_t error;
178+
if (!ip_name_lookup_resolve_addresses(
179+
__wasi_sockets_utils__borrow_network(), &name, &stream,
180+
&error))
181+
return map_error(error);
182+
183+
int ret = 0;
184+
ip_name_lookup_borrow_resolve_address_stream_t stream_borrow =
185+
ip_name_lookup_borrow_resolve_address_stream(stream);
186+
// The 'serv' parameter can be either a port number or a service name.
187+
int port = 0;
188+
uint16_t protocol = SERVICE_PROTOCOL_TCP;
189+
if (serv != NULL) {
190+
port = __wasi_sockets_utils__parse_port(serv);
191+
if (port < 0) {
192+
const service_entry_t *service = __wasi_sockets_utils__get_service_entry_by_name(serv);
193+
if (service) {
194+
port = service->port;
195+
protocol = service->protocol;
196+
} else {
197+
ret = EAI_NONAME;
198+
}
199+
}
200+
}
201+
202+
poll_own_pollable_t pollable;
203+
pollable.__handle = 0;
204+
205+
while (ret == 0) {
206+
ip_name_lookup_option_ip_address_t address;
207+
if (!ip_name_lookup_method_resolve_address_stream_resolve_next_address(
208+
stream_borrow, &address, &error)) {
209+
if (error != NETWORK_ERROR_CODE_WOULD_BLOCK) {
210+
freeaddrinfo(*res);
211+
ret = map_error(error);
212+
break;
213+
}
214+
215+
if (pollable.__handle == 0) {
216+
pollable = ip_name_lookup_method_resolve_address_stream_subscribe(
217+
stream_borrow);
218+
}
219+
poll_method_pollable_block(poll_borrow_pollable(pollable));
220+
continue;
221+
}
222+
if (!address.is_some)
223+
break;
224+
if (protocol & SERVICE_PROTOCOL_TCP) {
225+
ret = add_addr(address, htons(port), SOCK_STREAM,
226+
hint, &current, res);
227+
if (ret)
228+
break;
229+
}
230+
if (protocol & SERVICE_PROTOCOL_UDP) {
231+
ret = add_addr(address, htons(port), SOCK_DGRAM,
232+
hint, &current, res);
233+
if (ret)
234+
break;
235+
}
236+
}
237+
238+
if (pollable.__handle != 0)
239+
poll_pollable_drop_own(pollable);
240+
ip_name_lookup_resolve_address_stream_drop_own(stream);
241+
return ret;
237242
}
238243

239244
void freeaddrinfo(struct addrinfo *p)

0 commit comments

Comments
 (0)