1111#include "py/mperrno.h"
1212#include "py/runtime.h"
1313#include "shared-bindings/socketpool/SocketPool.h"
14+ #include "common-hal/socketpool/__init__.h"
15+ #include "common-hal/wifi/__init__.h"
1416#if CIRCUITPY_SSL
1517#include "shared-bindings/ssl/SSLSocket.h"
1618#include "shared-module/ssl/SSLSocket.h"
2527#include "components/lwip/lwip/src/include/lwip/netdb.h"
2628#include "components/vfs/include/esp_vfs_eventfd.h"
2729
30+ void socketpool_resolve_host_or_throw (int family , int type , const char * hostname , struct sockaddr_storage * addr , int port ) {
31+ struct addrinfo * result_i ;
32+ const struct addrinfo hints = {
33+ .ai_family = family ,
34+ .ai_socktype = type ,
35+ };
36+ int error = socketpool_getaddrinfo_common (hostname , port , & hints , & result_i );
37+ if (error != 0 || result_i == NULL ) {
38+ common_hal_socketpool_socketpool_raise_gaierror_noname ();
39+ }
40+ memcpy (addr , result_i -> ai_addr , sizeof (struct sockaddr_storage ));
41+ lwip_freeaddrinfo (result_i );
42+ }
43+
44+ static void resolve_host_or_throw (socketpool_socket_obj_t * self , const char * hostname , struct sockaddr_storage * addr , int port ) {
45+ socketpool_resolve_host_or_throw (self -> family , self -> type , hostname , addr , port );
46+ }
47+
2848StackType_t socket_select_stack [2 * configMINIMAL_STACK_SIZE ];
2949
3050/* Socket state table:
@@ -175,7 +195,7 @@ static bool _socketpool_socket(socketpool_socketpool_obj_t *self,
175195 if (family == SOCKETPOOL_AF_INET ) {
176196 addr_family = AF_INET ;
177197 ipproto = IPPROTO_IP ;
178- #if LWIP_IPV6
198+ #if CIRCUITPY_SOCKETPOOL_IPV6
179199 } else { // INET6
180200 addr_family = AF_INET6 ;
181201 ipproto = IPPROTO_IPV6 ;
@@ -230,8 +250,14 @@ bool socketpool_socket(socketpool_socketpool_obj_t *self,
230250
231251socketpool_socket_obj_t * common_hal_socketpool_socket (socketpool_socketpool_obj_t * self ,
232252 socketpool_socketpool_addressfamily_t family , socketpool_socketpool_sock_t type , int proto ) {
233- if (family != SOCKETPOOL_AF_INET ) {
234- mp_raise_NotImplementedError (MP_ERROR_TEXT ("Only IPv4 sockets supported" ));
253+ switch (family ) {
254+ #if CIRCUITPY_SOCKETPOOL_IPV6
255+ case SOCKETPOOL_AF_INET6 :
256+ #endif
257+ case SOCKETPOOL_AF_INET :
258+ break ;
259+ default :
260+ mp_raise_NotImplementedError (MP_ERROR_TEXT ("Unsupported socket type" ));
235261 }
236262
237263 socketpool_socket_obj_t * sock = m_new_obj_with_finaliser (socketpool_socket_obj_t );
@@ -244,9 +270,9 @@ socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_
244270 return sock ;
245271}
246272
247- int socketpool_socket_accept (socketpool_socket_obj_t * self , uint8_t * ip , uint32_t * port , socketpool_socket_obj_t * accepted ) {
248- struct sockaddr_in accept_addr ;
249- socklen_t socklen = sizeof (accept_addr );
273+ int socketpool_socket_accept (socketpool_socket_obj_t * self , mp_obj_t * peer_out , socketpool_socket_obj_t * accepted ) {
274+ struct sockaddr_storage peer_addr ;
275+ socklen_t socklen = sizeof (peer_addr );
250276 int newsoc = -1 ;
251277 bool timed_out = false;
252278 uint64_t start_ticks = supervisor_ticks_ms64 ();
@@ -257,20 +283,17 @@ int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_
257283 timed_out = supervisor_ticks_ms64 () - start_ticks >= self -> timeout_ms ;
258284 }
259285 RUN_BACKGROUND_TASKS ;
260- newsoc = lwip_accept (self -> num , (struct sockaddr * )& accept_addr , & socklen );
286+ newsoc = lwip_accept (self -> num , (struct sockaddr * )& peer_addr , & socklen );
261287 // In non-blocking mode, fail instead of timing out
262288 if (newsoc == -1 && (self -> timeout_ms == 0 || mp_hal_is_interrupted ())) {
263289 return - MP_EAGAIN ;
264290 }
265291 }
266292
267- if (!timed_out ) {
268- // harmless on failure but avoiding memcpy is faster
269- memcpy ((void * )ip , (void * )& accept_addr .sin_addr .s_addr , sizeof (accept_addr .sin_addr .s_addr ));
270- * port = accept_addr .sin_port ;
271- } else {
293+ if (timed_out ) {
272294 return - ETIMEDOUT ;
273295 }
296+
274297 if (newsoc < 0 ) {
275298 return - MP_EBADF ;
276299 }
@@ -295,13 +318,16 @@ int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_
295318 accepted -> type = self -> type ;
296319 }
297320
321+ if (peer_out ) {
322+ * peer_out = sockaddr_to_tuple (& peer_addr );
323+ }
324+
298325 return newsoc ;
299326}
300327
301- socketpool_socket_obj_t * common_hal_socketpool_socket_accept (socketpool_socket_obj_t * self ,
302- uint8_t * ip , uint32_t * port ) {
328+ socketpool_socket_obj_t * common_hal_socketpool_socket_accept (socketpool_socket_obj_t * self , mp_obj_t * peer_out ) {
303329 socketpool_socket_obj_t * sock = m_new_obj_with_finaliser (socketpool_socket_obj_t );
304- int newsoc = socketpool_socket_accept (self , ip , port , NULL );
330+ int newsoc = socketpool_socket_accept (self , peer_out , NULL );
305331
306332 if (newsoc > 0 ) {
307333 // Create the socket
@@ -321,20 +347,35 @@ socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_o
321347
322348size_t common_hal_socketpool_socket_bind (socketpool_socket_obj_t * self ,
323349 const char * host , size_t hostlen , uint32_t port ) {
324- struct sockaddr_in bind_addr ;
350+ struct sockaddr_storage bind_addr ;
325351 const char * broadcast = "<broadcast>" ;
326- uint32_t ip ;
327- if (hostlen == 0 ) {
328- ip = IPADDR_ANY ;
329- } else if (hostlen == strlen (broadcast ) &&
330- memcmp (host , broadcast , strlen (broadcast )) == 0 ) {
331- ip = IPADDR_BROADCAST ;
332- } else {
333- ip = inet_addr (host );
352+
353+ bind_addr .ss_family = self -> family ;
354+
355+ #if CIRCUITPY_SOCKETPOOL_IPV6
356+ if (self -> family == AF_INET6 ) {
357+ struct sockaddr_in6 * addr6 = (void * )& bind_addr ;
358+ addr6 -> sin6_port = htons (port );
359+ // no ipv6 broadcast
360+ if (hostlen == 0 ) {
361+ memset (& addr6 -> sin6_addr , 0 , sizeof (addr6 -> sin6_addr ));
362+ } else {
363+ socketpool_resolve_host_or_throw (self -> family , self -> type , host , & bind_addr , port );
364+ }
365+ } else
366+ #endif
367+ {
368+ struct sockaddr_in * addr4 = (void * )& bind_addr ;
369+ addr4 -> sin_port = htons (port );
370+ if (hostlen == 0 ) {
371+ addr4 -> sin_addr .s_addr = IPADDR_ANY ;
372+ } else if (hostlen == strlen (broadcast ) &&
373+ memcmp (host , broadcast , strlen (broadcast )) == 0 ) {
374+ addr4 -> sin_addr .s_addr = IPADDR_BROADCAST ;
375+ } else {
376+ socketpool_resolve_host_or_throw (self -> family , self -> type , host , & bind_addr , port );
377+ }
334378 }
335- bind_addr .sin_addr .s_addr = ip ;
336- bind_addr .sin_family = AF_INET ;
337- bind_addr .sin_port = htons (port );
338379
339380 int result = lwip_bind (self -> num , (struct sockaddr * )& bind_addr , sizeof (bind_addr ));
340381 if (result == 0 ) {
@@ -376,34 +417,16 @@ void common_hal_socketpool_socket_close(socketpool_socket_obj_t *self) {
376417
377418void common_hal_socketpool_socket_connect (socketpool_socket_obj_t * self ,
378419 const char * host , size_t hostlen , uint32_t port ) {
379- const struct addrinfo hints = {
380- .ai_family = AF_INET ,
381- .ai_socktype = SOCK_STREAM ,
382- };
383- struct addrinfo * result_i ;
384- int error = lwip_getaddrinfo (host , NULL , & hints , & result_i );
385- if (error != 0 || result_i == NULL ) {
386- common_hal_socketpool_socketpool_raise_gaierror_noname ();
387- }
388-
389- // Set parameters
390- struct sockaddr_in dest_addr ;
391- #pragma GCC diagnostic push
392- #pragma GCC diagnostic ignored "-Wcast-align"
393- dest_addr .sin_addr .s_addr = ((struct sockaddr_in * )result_i -> ai_addr )-> sin_addr .s_addr ;
394- #pragma GCC diagnostic pop
395- lwip_freeaddrinfo (result_i );
396-
397- dest_addr .sin_family = AF_INET ;
398- dest_addr .sin_port = htons (port );
420+ struct sockaddr_storage addr ;
421+ resolve_host_or_throw (self , host , & addr , port );
399422
400423 // Replace above with function call -----
401424
402425 // Emulate SO_CONTIMEO, which is not implemented by lwip.
403426 // All our sockets are non-blocking, so we check the timeout ourselves.
404427
405428 int result = -1 ;
406- result = lwip_connect (self -> num , (struct sockaddr * )& dest_addr , sizeof ( struct sockaddr_in ) );
429+ result = lwip_connect (self -> num , (struct sockaddr * )& addr , addr . s2_len );
407430
408431 if (result == 0 ) {
409432 // Connected immediately.
@@ -483,9 +506,9 @@ bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *self, int back
483506}
484507
485508mp_uint_t common_hal_socketpool_socket_recvfrom_into (socketpool_socket_obj_t * self ,
486- uint8_t * buf , uint32_t len , uint8_t * ip , uint32_t * port ) {
509+ uint8_t * buf , uint32_t len , mp_obj_t * source_out ) {
487510
488- struct sockaddr_in source_addr ;
511+ struct sockaddr_storage source_addr ;
489512 socklen_t socklen = sizeof (source_addr );
490513
491514 // LWIP Socket
@@ -507,10 +530,7 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *se
507530 }
508531 }
509532
510- if (!timed_out ) {
511- memcpy ((void * )ip , (void * )& source_addr .sin_addr .s_addr , sizeof (source_addr .sin_addr .s_addr ));
512- * port = htons (source_addr .sin_port );
513- } else {
533+ if (timed_out ) {
514534 mp_raise_OSError (ETIMEDOUT );
515535 }
516536
@@ -519,6 +539,10 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *se
519539 return 0 ;
520540 }
521541
542+ if (source_out ) {
543+ * source_out = sockaddr_to_tuple (& source_addr );
544+ }
545+
522546 return received ;
523547}
524548
@@ -605,29 +629,10 @@ mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t *self, const
605629mp_uint_t common_hal_socketpool_socket_sendto (socketpool_socket_obj_t * self ,
606630 const char * host , size_t hostlen , uint32_t port , const uint8_t * buf , uint32_t len ) {
607631
608- // Set parameters
609- const struct addrinfo hints = {
610- .ai_family = AF_INET ,
611- .ai_socktype = SOCK_STREAM ,
612- };
613- struct addrinfo * result_i ;
614- int error = lwip_getaddrinfo (host , NULL , & hints , & result_i );
615- if (error != 0 || result_i == NULL ) {
616- common_hal_socketpool_socketpool_raise_gaierror_noname ();
617- }
618-
619- // Set parameters
620- struct sockaddr_in dest_addr ;
621- #pragma GCC diagnostic push
622- #pragma GCC diagnostic ignored "-Wcast-align"
623- dest_addr .sin_addr .s_addr = ((struct sockaddr_in * )result_i -> ai_addr )-> sin_addr .s_addr ;
624- #pragma GCC diagnostic pop
625- lwip_freeaddrinfo (result_i );
626-
627- dest_addr .sin_family = AF_INET ;
628- dest_addr .sin_port = htons (port );
632+ struct sockaddr_storage addr ;
633+ resolve_host_or_throw (self , host , & addr , port );
629634
630- int bytes_sent = lwip_sendto (self -> num , buf , len , 0 , (struct sockaddr * )& dest_addr , sizeof ( dest_addr ) );
635+ int bytes_sent = lwip_sendto (self -> num , buf , len , 0 , (struct sockaddr * )& addr , addr . s2_len );
631636 if (bytes_sent < 0 ) {
632637 mp_raise_BrokenPipeError ();
633638 return 0 ;
0 commit comments