@@ -22,37 +22,122 @@ void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *sel
2222
2323// common_hal_socketpool_socket is in socketpool/Socket.c to centralize open socket tracking.
2424
25- mp_obj_t common_hal_socketpool_socketpool_gethostbyname (socketpool_socketpool_obj_t * self ,
26- const char * host ) {
27-
25+ static int getaddrinfo_common (const char * host , int service , const struct addrinfo * hints , struct addrinfo * * res ) {
2826 // As of 2022, the version of lwip in esp-idf does not handle the
2927 // trailing-dot syntax of domain names, so emulate it.
3028 // Remove this once https://github.com/espressif/esp-idf/issues/10013 has
3129 // been implemented
32- size_t strlen_host = strlen (host );
33- if (strlen_host && host [strlen_host - 1 ] == '.' ) {
34- mp_obj_t nodot = mp_obj_new_str (host , strlen_host - 1 );
35- host = mp_obj_str_get_str (nodot );
30+ if (host ) {
31+ size_t strlen_host = strlen (host );
32+ if (strlen_host && host [strlen_host - 1 ] == '.' ) {
33+ mp_obj_t nodot = mp_obj_new_str (host , strlen_host - 1 );
34+ host = mp_obj_str_get_str (nodot );
35+ }
36+ }
37+
38+ char service_buf [6 ];
39+ snprintf (service_buf , sizeof (service_buf ), "%d" , service );
40+
41+ return lwip_getaddrinfo (host , service_buf , hints , res );
42+ }
43+
44+ static mp_obj_t format_address (const struct sockaddr * addr , int family ) {
45+ char ip_str [IPADDR_STRLEN_MAX ]; // big enough for any supported address type
46+ const struct sockaddr_in * a = (void * )addr ;
47+
48+ switch (family ) {
49+ #if CIRCUITPY_SOCKETPOOL_IPV6
50+ case AF_INET6 :
51+ inet_ntop (family , & ((const struct sockaddr_in6 * )a )-> sin6_addr , ip_str , sizeof (ip_str ));
52+ break ;
53+ #endif
54+ default :
55+ case AF_INET :
56+ inet_ntop (family , & ((const struct sockaddr_in * )a )-> sin_addr , ip_str , sizeof (ip_str ));
57+ break ;
3658 }
59+ return mp_obj_new_str (ip_str , strlen (ip_str ));
60+ }
61+
62+ mp_obj_t common_hal_socketpool_socketpool_gethostbyname (socketpool_socketpool_obj_t * self ,
63+ const char * host ) {
3764
3865 const struct addrinfo hints = {
3966 .ai_family = AF_INET ,
4067 .ai_socktype = SOCK_STREAM ,
4168 };
42- struct addrinfo * res ;
43- int err = lwip_getaddrinfo (host , NULL , & hints , & res );
69+ struct addrinfo * res = NULL ;
70+ int err = getaddrinfo_common (host , 0 , & hints , & res );
4471 if (err != 0 || res == NULL ) {
4572 return mp_const_none ;
4673 }
4774
48- #pragma GCC diagnostic push
49- #pragma GCC diagnostic ignored "-Wcast-align"
50- struct in_addr * addr = & ((struct sockaddr_in * )res -> ai_addr )-> sin_addr ;
51- #pragma GCC diagnostic pop
52- char ip_str [IP4ADDR_STRLEN_MAX ];
53- inet_ntoa_r (* addr , ip_str , IP4ADDR_STRLEN_MAX );
54- mp_obj_t ip_obj = mp_obj_new_str (ip_str , strlen (ip_str ));
55- lwip_freeaddrinfo (res );
75+ nlr_buf_t nlr ;
76+ if (nlr_push (& nlr ) == 0 ) {
77+ mp_obj_t result = format_address (res -> ai_addr , res -> ai_family );
78+ nlr_pop ();
79+ lwip_freeaddrinfo (res );
80+ return result ;
81+ } else {
82+ lwip_freeaddrinfo (res );
83+ nlr_raise (MP_OBJ_FROM_PTR (nlr .ret_val ));
84+ };
85+ }
86+
87+ #if CIRCUITPY_SOCKETPOOL_IPV6
88+ static mp_obj_t convert_sockaddr (const struct addrinfo * ai , int port ) {
89+ mp_int_t n_tuple = ai -> ai_family == AF_INET6 ? 4 : 2 ;
90+ mp_obj_tuple_t * result = MP_OBJ_TO_PTR (mp_obj_new_tuple (n_tuple , NULL ));
91+ result -> items [0 ] = format_address (ai -> ai_addr , ai -> ai_family );
92+ result -> items [1 ] = MP_OBJ_NEW_SMALL_INT (port );
93+ if (ai -> ai_family == AF_INET6 ) {
94+ const struct sockaddr_in6 * ai6 = (void * )ai -> ai_addr ;
95+ result -> items [2 ] = MP_OBJ_NEW_SMALL_INT (ai6 -> sin6_flowinfo );
96+ result -> items [3 ] = MP_OBJ_NEW_SMALL_INT (ai6 -> sin6_scope_id );
97+ }
98+ return result ;
99+ }
56100
57- return ip_obj ;
101+ static mp_obj_t convert_addrinfo (const struct addrinfo * ai , int port ) {
102+ MP_STATIC_ASSERT (AF_INET == SOCKETPOOL_AF_INET );
103+ MP_STATIC_ASSERT (AF_INET6 == SOCKETPOOL_AF_INET6 );
104+ // MP_STATIC_ASSERT(AF_UNSPEC == SOCKETPOOL_AF_UNSPEC);
105+ mp_obj_tuple_t * result = MP_OBJ_TO_PTR (mp_obj_new_tuple (5 , NULL ));
106+ result -> items [0 ] = MP_OBJ_NEW_SMALL_INT (ai -> ai_family );
107+ result -> items [1 ] = MP_OBJ_NEW_SMALL_INT (ai -> ai_socktype );
108+ result -> items [2 ] = MP_OBJ_NEW_SMALL_INT (ai -> ai_protocol );
109+ result -> items [3 ] = ai -> ai_canonname ? mp_obj_new_str (ai -> ai_canonname , strlen (ai -> ai_canonname )) : MP_OBJ_NEW_QSTR (MP_QSTR_ );
110+ result -> items [4 ] = convert_sockaddr (ai , port );
111+ return result ;
112+ }
113+
114+ mp_obj_t common_hal_socketpool_getaddrinfo_raise (socketpool_socketpool_obj_t * self , const char * host , int port , int family , int type , int proto , int flags ) {
115+ MP_STATIC_ASSERT (LWIP_IPV6 );
116+ const struct addrinfo hints = {
117+ .ai_flags = flags ,
118+ .ai_family = family ,
119+ .ai_protocol = proto ,
120+ .ai_socktype = type ,
121+ };
122+
123+ struct addrinfo * res = NULL ;
124+ int err = getaddrinfo_common (host , port , & hints , & res );
125+ if (err != 0 || res == NULL ) {
126+ common_hal_socketpool_socketpool_raise_gaierror_noname ();
127+ }
128+
129+ nlr_buf_t nlr ;
130+ if (nlr_push (& nlr ) == 0 ) {
131+ mp_obj_t result = mp_obj_new_list (0 , NULL );
132+ for (struct addrinfo * ai = res ; ai ; ai = ai -> ai_next ) {
133+ mp_obj_list_append (result , convert_addrinfo (ai , port ));
134+ }
135+ nlr_pop ();
136+ lwip_freeaddrinfo (res );
137+ return result ;
138+ } else {
139+ lwip_freeaddrinfo (res );
140+ nlr_raise (MP_OBJ_FROM_PTR (nlr .ret_val ));
141+ }
58142}
143+ #endif
0 commit comments