Skip to content

Commit 09ed5bc

Browse files
committed
extmod/modlwip: Rework getaddrinfo() data passing.
The code is based on Damien George's implementation for esp8266 port, avoids use of global variables and associated re-entrancy issues, and fixes returning stale data in some cases.
1 parent 21b7460 commit 09ed5bc

File tree

1 file changed

+36
-31
lines changed

1 file changed

+36
-31
lines changed

extmod/modlwip.c

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -284,19 +284,6 @@ STATIC err_t _lwip_tcp_recv(void *arg, struct tcp_pcb *tcpb, struct pbuf *p, err
284284
return ERR_OK;
285285
}
286286

287-
STATIC uint8_t lwip_dns_returned;
288-
STATIC uint8_t lwip_dns_result[4];
289-
290-
// Callback for incoming DNS requests. Just set our results.
291-
STATIC void _lwip_dns_incoming(const char *name, ip_addr_t *addr, void *callback_arg) {
292-
if (addr != NULL) {
293-
lwip_dns_returned = 1;
294-
memcpy(lwip_dns_result, addr, sizeof(lwip_dns_result));
295-
} else {
296-
lwip_dns_returned = 2;
297-
}
298-
}
299-
300287
/*******************************************************************************/
301288
// Functions for socket send/recieve operations. Socket send/recv and friends call
302289
// these to do the work.
@@ -999,41 +986,59 @@ STATIC mp_obj_t mod_lwip_callback() {
999986
}
1000987
MP_DEFINE_CONST_FUN_OBJ_0(mod_lwip_callback_obj, mod_lwip_callback);
1001988

989+
typedef struct _getaddrinfo_state_t {
990+
volatile int status;
991+
volatile ip_addr_t ipaddr;
992+
} getaddrinfo_state_t;
993+
994+
// Callback for incoming DNS requests.
995+
STATIC void lwip_getaddrinfo_cb(const char *name, ip_addr_t *ipaddr, void *arg) {
996+
getaddrinfo_state_t *state = arg;
997+
if (ipaddr != NULL) {
998+
state->status = 1;
999+
state->ipaddr = *ipaddr;
1000+
} else {
1001+
// error
1002+
state->status = -2;
1003+
}
1004+
}
1005+
10021006
// lwip.getaddrinfo
10031007
STATIC mp_obj_t lwip_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
10041008
mp_uint_t hlen;
10051009
const char *host = mp_obj_str_get_data(host_in, &hlen);
10061010
mp_int_t port = mp_obj_get_int(port_in);
10071011

1008-
ip_addr_t result;
1009-
lwip_dns_returned = 0;
1012+
getaddrinfo_state_t state;
1013+
state.status = 0;
10101014

1011-
switch (dns_gethostbyname(host, &result, _lwip_dns_incoming, NULL)) {
1012-
case ERR_OK: {
1013-
break;
1014-
}
1015-
case ERR_INPROGRESS: {
1016-
while(!lwip_dns_returned) {
1015+
err_t ret = dns_gethostbyname(host, (ip_addr_t*)&state.ipaddr, lwip_getaddrinfo_cb, &state);
1016+
switch (ret) {
1017+
case ERR_OK:
1018+
// cached
1019+
state.status = 1;
1020+
break;
1021+
case ERR_INPROGRESS:
1022+
while (state.status == 0) {
10171023
poll_sockets();
10181024
}
1019-
if (lwip_dns_returned == 2) {
1020-
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOENT)));
1021-
}
10221025
break;
1023-
}
1024-
default: {
1025-
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOENT)));
1026-
}
1026+
default:
1027+
state.status = ret;
1028+
}
1029+
1030+
if (state.status < 0) {
1031+
// TODO: CPython raises gaierror, we raise with native lwIP negative error
1032+
// values, to differentiate from normal errno's at least in such way.
1033+
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(state.status)));
10271034
}
10281035

1029-
uint8_t out_ip[NETUTILS_IPV4ADDR_BUFSIZE];
1030-
memcpy(out_ip, lwip_dns_result, sizeof(lwip_dns_result));
10311036
mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
10321037
tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET);
10331038
tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM);
10341039
tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
10351040
tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
1036-
tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_BIG);
1041+
tuple->items[4] = netutils_format_inet_addr((uint8_t*)&state.ipaddr, port, NETUTILS_BIG);
10371042
return mp_obj_new_list(1, (mp_obj_t*)&tuple);
10381043
}
10391044
STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_getaddrinfo_obj, lwip_getaddrinfo);

0 commit comments

Comments
 (0)