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.
This commit is contained in:
parent
21b74604f9
commit
09ed5bcbbb
@ -284,19 +284,6 @@ STATIC err_t _lwip_tcp_recv(void *arg, struct tcp_pcb *tcpb, struct pbuf *p, err
|
|||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC uint8_t lwip_dns_returned;
|
|
||||||
STATIC uint8_t lwip_dns_result[4];
|
|
||||||
|
|
||||||
// Callback for incoming DNS requests. Just set our results.
|
|
||||||
STATIC void _lwip_dns_incoming(const char *name, ip_addr_t *addr, void *callback_arg) {
|
|
||||||
if (addr != NULL) {
|
|
||||||
lwip_dns_returned = 1;
|
|
||||||
memcpy(lwip_dns_result, addr, sizeof(lwip_dns_result));
|
|
||||||
} else {
|
|
||||||
lwip_dns_returned = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************************/
|
/*******************************************************************************/
|
||||||
// Functions for socket send/recieve operations. Socket send/recv and friends call
|
// Functions for socket send/recieve operations. Socket send/recv and friends call
|
||||||
// these to do the work.
|
// these to do the work.
|
||||||
@ -999,41 +986,59 @@ STATIC mp_obj_t mod_lwip_callback() {
|
|||||||
}
|
}
|
||||||
MP_DEFINE_CONST_FUN_OBJ_0(mod_lwip_callback_obj, mod_lwip_callback);
|
MP_DEFINE_CONST_FUN_OBJ_0(mod_lwip_callback_obj, mod_lwip_callback);
|
||||||
|
|
||||||
|
typedef struct _getaddrinfo_state_t {
|
||||||
|
volatile int status;
|
||||||
|
volatile ip_addr_t ipaddr;
|
||||||
|
} getaddrinfo_state_t;
|
||||||
|
|
||||||
|
// Callback for incoming DNS requests.
|
||||||
|
STATIC void lwip_getaddrinfo_cb(const char *name, ip_addr_t *ipaddr, void *arg) {
|
||||||
|
getaddrinfo_state_t *state = arg;
|
||||||
|
if (ipaddr != NULL) {
|
||||||
|
state->status = 1;
|
||||||
|
state->ipaddr = *ipaddr;
|
||||||
|
} else {
|
||||||
|
// error
|
||||||
|
state->status = -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// lwip.getaddrinfo
|
// lwip.getaddrinfo
|
||||||
STATIC mp_obj_t lwip_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
|
STATIC mp_obj_t lwip_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
|
||||||
mp_uint_t hlen;
|
mp_uint_t hlen;
|
||||||
const char *host = mp_obj_str_get_data(host_in, &hlen);
|
const char *host = mp_obj_str_get_data(host_in, &hlen);
|
||||||
mp_int_t port = mp_obj_get_int(port_in);
|
mp_int_t port = mp_obj_get_int(port_in);
|
||||||
|
|
||||||
ip_addr_t result;
|
getaddrinfo_state_t state;
|
||||||
lwip_dns_returned = 0;
|
state.status = 0;
|
||||||
|
|
||||||
switch (dns_gethostbyname(host, &result, _lwip_dns_incoming, NULL)) {
|
err_t ret = dns_gethostbyname(host, (ip_addr_t*)&state.ipaddr, lwip_getaddrinfo_cb, &state);
|
||||||
case ERR_OK: {
|
switch (ret) {
|
||||||
break;
|
case ERR_OK:
|
||||||
}
|
// cached
|
||||||
case ERR_INPROGRESS: {
|
state.status = 1;
|
||||||
while(!lwip_dns_returned) {
|
break;
|
||||||
|
case ERR_INPROGRESS:
|
||||||
|
while (state.status == 0) {
|
||||||
poll_sockets();
|
poll_sockets();
|
||||||
}
|
}
|
||||||
if (lwip_dns_returned == 2) {
|
|
||||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOENT)));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
default:
|
||||||
default: {
|
state.status = ret;
|
||||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOENT)));
|
}
|
||||||
}
|
|
||||||
|
if (state.status < 0) {
|
||||||
|
// TODO: CPython raises gaierror, we raise with native lwIP negative error
|
||||||
|
// values, to differentiate from normal errno's at least in such way.
|
||||||
|
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(state.status)));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t out_ip[NETUTILS_IPV4ADDR_BUFSIZE];
|
|
||||||
memcpy(out_ip, lwip_dns_result, sizeof(lwip_dns_result));
|
|
||||||
mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
|
mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
|
||||||
tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET);
|
tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET);
|
||||||
tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM);
|
tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM);
|
||||||
tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
|
tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
|
||||||
tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
|
tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
|
||||||
tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_BIG);
|
tuple->items[4] = netutils_format_inet_addr((uint8_t*)&state.ipaddr, port, NETUTILS_BIG);
|
||||||
return mp_obj_new_list(1, (mp_obj_t*)&tuple);
|
return mp_obj_new_list(1, (mp_obj_t*)&tuple);
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_getaddrinfo_obj, lwip_getaddrinfo);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_getaddrinfo_obj, lwip_getaddrinfo);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user