Skip to content

Commit 0c57979

Browse files
committed
zephyr/modusocket: Implement getaddrinfo().
1 parent 86c4544 commit 0c57979

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

zephyr/modusocket.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <version.h>
3737
#include <net/net_context.h>
3838
#include <net/net_pkt.h>
39+
#include <net/dns_resolve.h>
3940

4041
#define DEBUG 0
4142
#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
114115
sockaddr_in->sin_port = htons(mp_obj_get_int(addr_items[1]));
115116
}
116117

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+
117139
// Copy data from Zephyr net_buf chain into linear buffer.
118140
// We don't use net_pkt_read(), because it's weird (e.g., we'd like to
119141
// free processed data fragment ASAP, while net_pkt_read() holds onto
@@ -507,6 +529,69 @@ STATIC const mp_obj_type_t socket_type = {
507529
.locals_dict = (mp_obj_t)&socket_locals_dict,
508530
};
509531

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+
510595
STATIC mp_obj_t pkt_get_info(void) {
511596
struct k_mem_slab *rx, *tx;
512597
struct net_buf_pool *rx_data, *tx_data;
@@ -534,6 +619,7 @@ STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = {
534619
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOL_SOCKET), MP_OBJ_NEW_SMALL_INT(1) },
535620
{ MP_OBJ_NEW_QSTR(MP_QSTR_SO_REUSEADDR), MP_OBJ_NEW_SMALL_INT(2) },
536621

622+
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&mod_getaddrinfo_obj },
537623
{ MP_OBJ_NEW_QSTR(MP_QSTR_pkt_get_info), (mp_obj_t)&pkt_get_info_obj },
538624
};
539625

zephyr/prj_base.conf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ CONFIG_NET_TCP=y
1717
CONFIG_TEST_RANDOM_GENERATOR=y
1818
CONFIG_NET_NBUF_RX_COUNT=5
1919

20+
# DNS
21+
CONFIG_DNS_RESOLVER=y
22+
CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=2
23+
CONFIG_DNS_SERVER_IP_ADDRESSES=y
24+
CONFIG_DNS_SERVER1="192.0.2.2"
25+
2026
# Required for usocket.pkt_get_info()
2127
CONFIG_NET_BUF_POOL_USAGE=y
2228

0 commit comments

Comments
 (0)