|
36 | 36 | #include <version.h>
|
37 | 37 | #include <net/net_context.h>
|
38 | 38 | #include <net/net_pkt.h>
|
| 39 | +#include <net/dns_resolve.h> |
39 | 40 |
|
40 | 41 | #define DEBUG 0
|
41 | 42 | #if DEBUG // print debugging info
|
@@ -114,6 +115,27 @@ STATIC void parse_inet_addr(socket_obj_t *socket, mp_obj_t addr_in, struct socka
|
114 | 115 | sockaddr_in->sin_port = htons(mp_obj_get_int(addr_items[1]));
|
115 | 116 | }
|
116 | 117 |
|
| 118 | +STATIC mp_obj_t format_inet_addr(struct sockaddr *addr, mp_obj_t port) { |
| 119 | + // We employ the fact that port and address offsets are the same for IPv4 & IPv6 |
| 120 | + struct sockaddr_in6 *sockaddr_in6 = (struct sockaddr_in6*)addr; |
| 121 | + char buf[40]; |
| 122 | + net_addr_ntop(addr->family, &sockaddr_in6->sin6_addr, buf, sizeof(buf)); |
| 123 | + mp_obj_tuple_t *tuple = mp_obj_new_tuple(addr->family == AF_INET ? 2 : 4, NULL); |
| 124 | + |
| 125 | + tuple->items[0] = mp_obj_new_str(buf, strlen(buf), false); |
| 126 | + // We employ the fact that port offset is the same for IPv4 & IPv6 |
| 127 | + // not filled in |
| 128 | + //tuple->items[1] = mp_obj_new_int(ntohs(((struct sockaddr_in*)addr)->sin_port)); |
| 129 | + tuple->items[1] = port; |
| 130 | + |
| 131 | + if (addr->family == AF_INET6) { |
| 132 | + tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); // flow_info |
| 133 | + tuple->items[3] = MP_OBJ_NEW_SMALL_INT(sockaddr_in6->sin6_scope_id); |
| 134 | + } |
| 135 | + |
| 136 | + return MP_OBJ_FROM_PTR(tuple); |
| 137 | +} |
| 138 | + |
117 | 139 | // Copy data from Zephyr net_buf chain into linear buffer.
|
118 | 140 | // We don't use net_pkt_read(), because it's weird (e.g., we'd like to
|
119 | 141 | // free processed data fragment ASAP, while net_pkt_read() holds onto
|
@@ -507,6 +529,69 @@ STATIC const mp_obj_type_t socket_type = {
|
507 | 529 | .locals_dict = (mp_obj_t)&socket_locals_dict,
|
508 | 530 | };
|
509 | 531 |
|
| 532 | +// |
| 533 | +// getaddrinfo() implementation |
| 534 | +// |
| 535 | + |
| 536 | +typedef struct _getaddrinfo_state_t { |
| 537 | + mp_obj_t result; |
| 538 | + struct k_sem sem; |
| 539 | + mp_obj_t port; |
| 540 | +} getaddrinfo_state_t; |
| 541 | + |
| 542 | +void dns_resolve_cb(enum dns_resolve_status status, struct dns_addrinfo *info, void *user_data) { |
| 543 | + getaddrinfo_state_t *state = user_data; |
| 544 | + |
| 545 | + if (info == NULL) { |
| 546 | + k_sem_give(&state->sem); |
| 547 | + return; |
| 548 | + } |
| 549 | + |
| 550 | + mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); |
| 551 | + tuple->items[0] = MP_OBJ_NEW_SMALL_INT(info->ai_family); |
| 552 | + // info->ai_socktype not filled |
| 553 | + tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCK_STREAM); |
| 554 | + // info->ai_protocol not filled |
| 555 | + tuple->items[2] = MP_OBJ_NEW_SMALL_INT(IPPROTO_TCP); |
| 556 | + tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); |
| 557 | + tuple->items[4] = format_inet_addr(&info->ai_addr, state->port); |
| 558 | + mp_obj_list_append(state->result, MP_OBJ_FROM_PTR(tuple)); |
| 559 | +} |
| 560 | + |
| 561 | +STATIC mp_obj_t mod_getaddrinfo(size_t n_args, const mp_obj_t *args) { |
| 562 | + mp_obj_t host_in = args[0], port_in = args[1]; |
| 563 | + const char *host = mp_obj_str_get_str(host_in); |
| 564 | + mp_int_t family = 0; |
| 565 | + if (n_args > 2) { |
| 566 | + family = mp_obj_get_int(args[2]); |
| 567 | + } |
| 568 | + |
| 569 | + getaddrinfo_state_t state; |
| 570 | + // Just validate that it's int |
| 571 | + (void)mp_obj_get_int(port_in); |
| 572 | + state.port = port_in; |
| 573 | + state.result = mp_obj_new_list(0, NULL); |
| 574 | + k_sem_init(&state.sem, 0, UINT_MAX); |
| 575 | + |
| 576 | + int status; |
| 577 | + for (int i = 2; i--;) { |
| 578 | + int type = (family != AF_INET6 ? DNS_QUERY_TYPE_A : DNS_QUERY_TYPE_AAAA); |
| 579 | + status = dns_get_addr_info(host, type, NULL, dns_resolve_cb, &state, 3000); |
| 580 | + if (status < 0) { |
| 581 | + mp_raise_OSError(status); |
| 582 | + } |
| 583 | + k_sem_take(&state.sem, K_FOREVER); |
| 584 | + if (family != 0) { |
| 585 | + break; |
| 586 | + } |
| 587 | + family = AF_INET6; |
| 588 | + } |
| 589 | + |
| 590 | + return state.result; |
| 591 | +} |
| 592 | +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_getaddrinfo_obj, 2, 3, mod_getaddrinfo); |
| 593 | + |
| 594 | + |
510 | 595 | STATIC mp_obj_t pkt_get_info(void) {
|
511 | 596 | struct k_mem_slab *rx, *tx;
|
512 | 597 | struct net_buf_pool *rx_data, *tx_data;
|
@@ -534,6 +619,7 @@ STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = {
|
534 | 619 | { MP_OBJ_NEW_QSTR(MP_QSTR_SOL_SOCKET), MP_OBJ_NEW_SMALL_INT(1) },
|
535 | 620 | { MP_OBJ_NEW_QSTR(MP_QSTR_SO_REUSEADDR), MP_OBJ_NEW_SMALL_INT(2) },
|
536 | 621 |
|
| 622 | + { MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&mod_getaddrinfo_obj }, |
537 | 623 | { MP_OBJ_NEW_QSTR(MP_QSTR_pkt_get_info), (mp_obj_t)&pkt_get_info_obj },
|
538 | 624 | };
|
539 | 625 |
|
|
0 commit comments