@@ -22,37 +22,122 @@ void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *sel
22
22
23
23
// common_hal_socketpool_socket is in socketpool/Socket.c to centralize open socket tracking.
24
24
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 ) {
28
26
// As of 2022, the version of lwip in esp-idf does not handle the
29
27
// trailing-dot syntax of domain names, so emulate it.
30
28
// Remove this once https://github.com/espressif/esp-idf/issues/10013 has
31
29
// 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 ;
36
58
}
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 ) {
37
64
38
65
const struct addrinfo hints = {
39
66
.ai_family = AF_INET ,
40
67
.ai_socktype = SOCK_STREAM ,
41
68
};
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 );
44
71
if (err != 0 || res == NULL ) {
45
72
return mp_const_none ;
46
73
}
47
74
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
+ }
56
100
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
+ }
58
142
}
143
+ #endif
0 commit comments