From eaa6f99d0e04a2921b7d8d523b659df770e952d3 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 10 Jul 2024 12:17:42 -0500 Subject: [PATCH 01/18] Add v6 address support to SocketPool.getaddrinfo (on espressif) --- .../common-hal/socketpool/SocketPool.c | 121 +++++++++++++++--- ports/espressif/mpconfigport.mk | 1 + py/circuitpy_mpconfig.mk | 3 + shared-bindings/socketpool/SocketPool.c | 11 ++ shared-bindings/socketpool/SocketPool.h | 4 + 5 files changed, 122 insertions(+), 18 deletions(-) diff --git a/ports/espressif/common-hal/socketpool/SocketPool.c b/ports/espressif/common-hal/socketpool/SocketPool.c index 1c5adf81aad4..31c12fd66779 100644 --- a/ports/espressif/common-hal/socketpool/SocketPool.c +++ b/ports/espressif/common-hal/socketpool/SocketPool.c @@ -22,37 +22,122 @@ void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *sel // common_hal_socketpool_socket is in socketpool/Socket.c to centralize open socket tracking. -mp_obj_t common_hal_socketpool_socketpool_gethostbyname(socketpool_socketpool_obj_t *self, - const char *host) { - +static int getaddrinfo_common(const char *host, int service, const struct addrinfo *hints, struct addrinfo **res) { // As of 2022, the version of lwip in esp-idf does not handle the // trailing-dot syntax of domain names, so emulate it. // Remove this once https://github.com/espressif/esp-idf/issues/10013 has // been implemented - size_t strlen_host = strlen(host); - if (strlen_host && host[strlen_host - 1] == '.') { - mp_obj_t nodot = mp_obj_new_str(host, strlen_host - 1); - host = mp_obj_str_get_str(nodot); + if (host) { + size_t strlen_host = strlen(host); + if (strlen_host && host[strlen_host - 1] == '.') { + mp_obj_t nodot = mp_obj_new_str(host, strlen_host - 1); + host = mp_obj_str_get_str(nodot); + } + } + + char service_buf[6]; + snprintf(service_buf, sizeof(service_buf), "%d", service); + + return lwip_getaddrinfo(host, service_buf, hints, res); +} + +static mp_obj_t format_address(const struct sockaddr *addr, int family) { + char ip_str[IPADDR_STRLEN_MAX]; // big enough for any supported address type + const struct sockaddr_in *a = (void *)addr; + + switch (family) { + #if CIRCUITPY_SOCKETPOOL_IPV6 + case AF_INET6: + inet_ntop(family, &((const struct sockaddr_in6 *)a)->sin6_addr, ip_str, sizeof(ip_str)); + break; + #endif + default: + case AF_INET: + inet_ntop(family, &((const struct sockaddr_in *)a)->sin_addr, ip_str, sizeof(ip_str)); + break; } + return mp_obj_new_str(ip_str, strlen(ip_str)); +} + +mp_obj_t common_hal_socketpool_socketpool_gethostbyname(socketpool_socketpool_obj_t *self, + const char *host) { const struct addrinfo hints = { .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, }; - struct addrinfo *res; - int err = lwip_getaddrinfo(host, NULL, &hints, &res); + struct addrinfo *res = NULL; + int err = getaddrinfo_common(host, 0, &hints, &res); if (err != 0 || res == NULL) { return mp_const_none; } - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wcast-align" - struct in_addr *addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr; - #pragma GCC diagnostic pop - char ip_str[IP4ADDR_STRLEN_MAX]; - inet_ntoa_r(*addr, ip_str, IP4ADDR_STRLEN_MAX); - mp_obj_t ip_obj = mp_obj_new_str(ip_str, strlen(ip_str)); - lwip_freeaddrinfo(res); + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_t result = format_address(res->ai_addr, res->ai_family); + nlr_pop(); + lwip_freeaddrinfo(res); + return result; + } else { + lwip_freeaddrinfo(res); + nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val)); + }; +} + +#if CIRCUITPY_SOCKETPOOL_IPV6 +static mp_obj_t convert_sockaddr(const struct addrinfo *ai, int port) { + mp_int_t n_tuple = ai->ai_family == AF_INET6 ? 4 : 2; + mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_tuple, NULL)); + result->items[0] = format_address(ai->ai_addr, ai->ai_family); + result->items[1] = MP_OBJ_NEW_SMALL_INT(port); + if (ai->ai_family == AF_INET6) { + const struct sockaddr_in6 *ai6 = (void *)ai->ai_addr; + result->items[2] = MP_OBJ_NEW_SMALL_INT(ai6->sin6_flowinfo); + result->items[3] = MP_OBJ_NEW_SMALL_INT(ai6->sin6_scope_id); + } + return result; +} - return ip_obj; +static mp_obj_t convert_addrinfo(const struct addrinfo *ai, int port) { + MP_STATIC_ASSERT(AF_INET == SOCKETPOOL_AF_INET); + MP_STATIC_ASSERT(AF_INET6 == SOCKETPOOL_AF_INET6); + // MP_STATIC_ASSERT(AF_UNSPEC == SOCKETPOOL_AF_UNSPEC); + mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); + result->items[0] = MP_OBJ_NEW_SMALL_INT(ai->ai_family); + result->items[1] = MP_OBJ_NEW_SMALL_INT(ai->ai_socktype); + result->items[2] = MP_OBJ_NEW_SMALL_INT(ai->ai_protocol); + result->items[3] = ai->ai_canonname ? mp_obj_new_str(ai->ai_canonname, strlen(ai->ai_canonname)) : MP_OBJ_NEW_QSTR(MP_QSTR_); + result->items[4] = convert_sockaddr(ai, port); + return result; +} + +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) { + MP_STATIC_ASSERT(LWIP_IPV6); + const struct addrinfo hints = { + .ai_flags = flags, + .ai_family = family, + .ai_protocol = proto, + .ai_socktype = type, + }; + + struct addrinfo *res = NULL; + int err = getaddrinfo_common(host, port, &hints, &res); + if (err != 0 || res == NULL) { + common_hal_socketpool_socketpool_raise_gaierror_noname(); + } + + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_t result = mp_obj_new_list(0, NULL); + for (struct addrinfo *ai = res; ai; ai = ai->ai_next) { + mp_obj_list_append(result, convert_addrinfo(ai, port)); + } + nlr_pop(); + lwip_freeaddrinfo(res); + return result; + } else { + lwip_freeaddrinfo(res); + nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val)); + } } +#endif diff --git a/ports/espressif/mpconfigport.mk b/ports/espressif/mpconfigport.mk index 14c3b83250f1..d431501129f6 100644 --- a/ports/espressif/mpconfigport.mk +++ b/ports/espressif/mpconfigport.mk @@ -49,6 +49,7 @@ CIRCUITPY_SYNTHIO_MAX_CHANNELS ?= 12 CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1 CIRCUITPY_WATCHDOG ?= 1 CIRCUITPY_WIFI ?= 1 +CIRCUITPY_SOCKETPOOL_IPV6 ?= 1 # Enable _eve module CIRCUITPY__EVE ?= 1 diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 5c0ba355ad74..e7900ce0696d 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -496,6 +496,9 @@ CFLAGS += -DCIRCUITPY_SKIP_SAFE_MODE_WAIT=$(CIRCUITPY_SKIP_SAFE_MODE_WAIT) CIRCUITPY_SOCKETPOOL ?= $(CIRCUITPY_WIFI) CFLAGS += -DCIRCUITPY_SOCKETPOOL=$(CIRCUITPY_SOCKETPOOL) +CIRCUITPY_SOCKETPOOL_IPV6 ?= 0 +CFLAGS += -DCIRCUITPY_SOCKETPOOL_IPV6=$(CIRCUITPY_SOCKETPOOL_IPV6) + CIRCUITPY_SSL ?= $(CIRCUITPY_WIFI) CFLAGS += -DCIRCUITPY_SSL=$(CIRCUITPY_SSL) diff --git a/shared-bindings/socketpool/SocketPool.c b/shared-bindings/socketpool/SocketPool.c index 2b4623323fa8..b75438403037 100644 --- a/shared-bindings/socketpool/SocketPool.c +++ b/shared-bindings/socketpool/SocketPool.c @@ -142,6 +142,16 @@ static mp_obj_t socketpool_socketpool_getaddrinfo(size_t n_args, const mp_obj_t mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + #if CIRCUITPY_SOCKETPOOL_IPV6 + return common_hal_socketpool_getaddrinfo_raise( + self, + mp_obj_str_get_str(args[ARG_host].u_obj), + args[ARG_port].u_int, + args[ARG_family].u_int, + args[ARG_type].u_int, + args[ARG_proto].u_int, + args[ARG_flags].u_int); + #else const char *host = mp_obj_str_get_str(args[ARG_host].u_obj); mp_int_t port = args[ARG_port].u_int; mp_obj_t ip_str = mp_const_none; @@ -164,6 +174,7 @@ static mp_obj_t socketpool_socketpool_getaddrinfo(size_t n_args, const mp_obj_t sockaddr->items[1] = MP_OBJ_NEW_SMALL_INT(port); tuple->items[4] = MP_OBJ_FROM_PTR(sockaddr); return mp_obj_new_list(1, (mp_obj_t *)&tuple); + #endif } static MP_DEFINE_CONST_FUN_OBJ_KW(socketpool_socketpool_getaddrinfo_obj, 1, socketpool_socketpool_getaddrinfo); diff --git a/shared-bindings/socketpool/SocketPool.h b/shared-bindings/socketpool/SocketPool.h index 7088961477f7..48acb05d97f2 100644 --- a/shared-bindings/socketpool/SocketPool.h +++ b/shared-bindings/socketpool/SocketPool.h @@ -32,3 +32,7 @@ bool socketpool_socket(socketpool_socketpool_obj_t *self, int proto, socketpool_socket_obj_t *sock); NORETURN void common_hal_socketpool_socketpool_raise_gaierror_noname(void); + +#if CIRCUITPY_SOCKETPOOL_IPV6 +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); +#endif From d612d182e8d20e780764a4687a4ee3919f3bb584 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 10 Jul 2024 12:18:37 -0500 Subject: [PATCH 02/18] espressif: Socket: pass correct family & type in connect, sendto Otherwise, it was not possible to interact with a v6 address, as `lwip_getaddrinfo` wouldn't resolve it. --- ports/espressif/common-hal/socketpool/Socket.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ports/espressif/common-hal/socketpool/Socket.c b/ports/espressif/common-hal/socketpool/Socket.c index 7a4634af495a..5a61234f69af 100644 --- a/ports/espressif/common-hal/socketpool/Socket.c +++ b/ports/espressif/common-hal/socketpool/Socket.c @@ -377,8 +377,8 @@ void common_hal_socketpool_socket_close(socketpool_socket_obj_t *self) { void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self, const char *host, size_t hostlen, uint32_t port) { const struct addrinfo hints = { - .ai_family = AF_INET, - .ai_socktype = SOCK_STREAM, + .ai_family = self->family, + .ai_socktype = self->type, }; struct addrinfo *result_i; int error = lwip_getaddrinfo(host, NULL, &hints, &result_i); @@ -607,8 +607,8 @@ mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *self, // Set parameters const struct addrinfo hints = { - .ai_family = AF_INET, - .ai_socktype = SOCK_STREAM, + .ai_family = self->family, + .ai_socktype = self->type, }; struct addrinfo *result_i; int error = lwip_getaddrinfo(host, NULL, &hints, &result_i); From 3b30f0cc36dcc87dc0e61f676aaac5c378246cbe Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 10 Jul 2024 12:56:07 -0500 Subject: [PATCH 03/18] espressif: allow socket(AF_INET6) --- locale/circuitpython.pot | 6 +++++- ports/espressif/common-hal/socketpool/Socket.c | 10 ++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index e707386d0a47..88e7ebd80b77 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -1177,6 +1177,7 @@ msgid "Interrupted by output function" msgstr "" #: ports/espressif/common-hal/espulp/ULP.c +#: ports/espressif/common-hal/microcontroller/Processor.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c @@ -1557,7 +1558,6 @@ msgstr "" msgid "Only IPv4 addresses supported" msgstr "" -#: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c msgid "Only IPv4 sockets supported" msgstr "" @@ -2219,6 +2219,10 @@ msgstr "" msgid "Unsupported hash algorithm" msgstr "" +#: ports/espressif/common-hal/socketpool/Socket.c +msgid "Unsupported socket type" +msgstr "" + #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/espressif/common-hal/dualbank/__init__.c msgid "Update failed" diff --git a/ports/espressif/common-hal/socketpool/Socket.c b/ports/espressif/common-hal/socketpool/Socket.c index 5a61234f69af..d624e9602afa 100644 --- a/ports/espressif/common-hal/socketpool/Socket.c +++ b/ports/espressif/common-hal/socketpool/Socket.c @@ -230,8 +230,14 @@ bool socketpool_socket(socketpool_socketpool_obj_t *self, socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_t *self, socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type, int proto) { - if (family != SOCKETPOOL_AF_INET) { - mp_raise_NotImplementedError(MP_ERROR_TEXT("Only IPv4 sockets supported")); + switch (family) { + #if CIRCUITPY_SOCKETPOOL_IPV6 + case SOCKETPOOL_AF_INET6: + #endif + case SOCKETPOOL_AF_INET: + break; + default: + mp_raise_NotImplementedError(MP_ERROR_TEXT("Unsupported socket type")); } socketpool_socket_obj_t *sock = m_new_obj_with_finaliser(socketpool_socket_obj_t); From 9088488d1ca484aec7bc27528e95faf244fc11a5 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 16 Jul 2024 12:27:19 -0500 Subject: [PATCH 04/18] WIP ipv6 works(-ish) * metro esp32s2 only, because that's what I had handy * nothing is started at boot; I hung it on `start_dhcp()` which is dubious * I get a stateless address (which doesn't seem to work) and a dhcpv6 address (which does) ``` >>> wifi.radio.ipv6_addresses ('FE80::7EDF:A1FF:FE00:518C', 'FD5F:3F5C:FE50:0:7EDF:A1FF:FE00:518C') ``` * depending whether a v4 or v6 dns server is configured, DNS resolution breaks wrong ipv4_dns is first 4 bytes of the v6 dns server address: ``` >>> wifi.radio.ipv4_dns 253.95.63.92 ``` * I can connect to a v4 or v6 SSH server on the local network and read its banner >>> s.close(); s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM); s.connect(("fd5f:3f5c:fe50:0:6d9:f5ff:fe1f:ce10", 22)) *** len[0]=28 *** len=28 family=10 port=5632 >>> s.recv_into(buf) 40 >>> bytes(buf) b'SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3\r\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' --- .../boards/adafruit_metro_esp32s2/sdkconfig | 4 ++ .../espressif/common-hal/socketpool/Socket.c | 66 +++++++------------ .../common-hal/socketpool/SocketPool.c | 7 +- .../common-hal/socketpool/__init__.h | 6 +- ports/espressif/common-hal/wifi/Radio.c | 32 +++++++++ shared-bindings/wifi/Radio.c | 17 +++++ shared-bindings/wifi/Radio.h | 2 + 7 files changed, 83 insertions(+), 51 deletions(-) diff --git a/ports/espressif/boards/adafruit_metro_esp32s2/sdkconfig b/ports/espressif/boards/adafruit_metro_esp32s2/sdkconfig index e69de29bb2d1..3258b81da529 100644 --- a/ports/espressif/boards/adafruit_metro_esp32s2/sdkconfig +++ b/ports/espressif/boards/adafruit_metro_esp32s2/sdkconfig @@ -0,0 +1,4 @@ + +CONFIG_LWIP_IPV6_AUTOCONFIG=y +CONFIG_LWIP_IPV6_RDNSS_MAX_DNS_SERVERS=2 +CONFIG_LWIP_IPV6_DHCP6=y diff --git a/ports/espressif/common-hal/socketpool/Socket.c b/ports/espressif/common-hal/socketpool/Socket.c index d624e9602afa..ba81b7a16b98 100644 --- a/ports/espressif/common-hal/socketpool/Socket.c +++ b/ports/espressif/common-hal/socketpool/Socket.c @@ -11,6 +11,7 @@ #include "py/mperrno.h" #include "py/runtime.h" #include "shared-bindings/socketpool/SocketPool.h" +#include "common-hal/socketpool/__init__.h" #if CIRCUITPY_SSL #include "shared-bindings/ssl/SSLSocket.h" #include "shared-module/ssl/SSLSocket.h" @@ -25,6 +26,20 @@ #include "components/lwip/lwip/src/include/lwip/netdb.h" #include "components/vfs/include/esp_vfs_eventfd.h" +static void resolve_host_or_throw(socketpool_socket_obj_t *self, const char *hostname, struct sockaddr_storage *addr, int port) { + struct addrinfo *result_i; + const struct addrinfo hints = { + .ai_family = self->family, + .ai_socktype = self->type, + }; + int error = socketpool_getaddrinfo_common(hostname, port, &hints, &result_i); + if (error != 0 || result_i == NULL) { + common_hal_socketpool_socketpool_raise_gaierror_noname(); + } + memcpy(addr, result_i->ai_addr, sizeof(struct sockaddr_storage)); + lwip_freeaddrinfo(result_i); +} + StackType_t socket_select_stack[2 * configMINIMAL_STACK_SIZE]; /* Socket state table: @@ -339,7 +354,7 @@ size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self, ip = inet_addr(host); } bind_addr.sin_addr.s_addr = ip; - bind_addr.sin_family = AF_INET; + bind_addr.sin_family = self->family; bind_addr.sin_port = htons(port); int result = lwip_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr)); @@ -382,26 +397,8 @@ void common_hal_socketpool_socket_close(socketpool_socket_obj_t *self) { void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self, const char *host, size_t hostlen, uint32_t port) { - const struct addrinfo hints = { - .ai_family = self->family, - .ai_socktype = self->type, - }; - struct addrinfo *result_i; - int error = lwip_getaddrinfo(host, NULL, &hints, &result_i); - if (error != 0 || result_i == NULL) { - common_hal_socketpool_socketpool_raise_gaierror_noname(); - } - - // Set parameters - struct sockaddr_in dest_addr; - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wcast-align" - dest_addr.sin_addr.s_addr = ((struct sockaddr_in *)result_i->ai_addr)->sin_addr.s_addr; - #pragma GCC diagnostic pop - lwip_freeaddrinfo(result_i); - - dest_addr.sin_family = AF_INET; - dest_addr.sin_port = htons(port); + struct sockaddr_storage addr; + resolve_host_or_throw(self, host, &addr, port); // Replace above with function call ----- @@ -409,7 +406,7 @@ void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self, // All our sockets are non-blocking, so we check the timeout ourselves. int result = -1; - result = lwip_connect(self->num, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in)); + result = lwip_connect(self->num, (struct sockaddr *)&addr, addr.s2_len); if (result == 0) { // Connected immediately. @@ -611,29 +608,10 @@ mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t *self, const mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *self, const char *host, size_t hostlen, uint32_t port, const uint8_t *buf, uint32_t len) { - // Set parameters - const struct addrinfo hints = { - .ai_family = self->family, - .ai_socktype = self->type, - }; - struct addrinfo *result_i; - int error = lwip_getaddrinfo(host, NULL, &hints, &result_i); - if (error != 0 || result_i == NULL) { - common_hal_socketpool_socketpool_raise_gaierror_noname(); - } - - // Set parameters - struct sockaddr_in dest_addr; - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wcast-align" - dest_addr.sin_addr.s_addr = ((struct sockaddr_in *)result_i->ai_addr)->sin_addr.s_addr; - #pragma GCC diagnostic pop - lwip_freeaddrinfo(result_i); - - dest_addr.sin_family = AF_INET; - dest_addr.sin_port = htons(port); + struct sockaddr_storage addr; + resolve_host_or_throw(self, host, &addr, port); - int bytes_sent = lwip_sendto(self->num, buf, len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); + int bytes_sent = lwip_sendto(self->num, buf, len, 0, (struct sockaddr *)&addr, addr.s2_len); if (bytes_sent < 0) { mp_raise_BrokenPipeError(); return 0; diff --git a/ports/espressif/common-hal/socketpool/SocketPool.c b/ports/espressif/common-hal/socketpool/SocketPool.c index 31c12fd66779..190724e0f76c 100644 --- a/ports/espressif/common-hal/socketpool/SocketPool.c +++ b/ports/espressif/common-hal/socketpool/SocketPool.c @@ -9,6 +9,7 @@ #include "py/runtime.h" #include "shared-bindings/wifi/__init__.h" +#include "common-hal/socketpool/__init__.h" #include "components/lwip/lwip/src/include/lwip/netdb.h" @@ -22,7 +23,7 @@ void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *sel // common_hal_socketpool_socket is in socketpool/Socket.c to centralize open socket tracking. -static int getaddrinfo_common(const char *host, int service, const struct addrinfo *hints, struct addrinfo **res) { +int socketpool_getaddrinfo_common(const char *host, int service, const struct addrinfo *hints, struct addrinfo **res) { // As of 2022, the version of lwip in esp-idf does not handle the // trailing-dot syntax of domain names, so emulate it. // Remove this once https://github.com/espressif/esp-idf/issues/10013 has @@ -67,7 +68,7 @@ mp_obj_t common_hal_socketpool_socketpool_gethostbyname(socketpool_socketpool_ob .ai_socktype = SOCK_STREAM, }; struct addrinfo *res = NULL; - int err = getaddrinfo_common(host, 0, &hints, &res); + int err = socketpool_getaddrinfo_common(host, 0, &hints, &res); if (err != 0 || res == NULL) { return mp_const_none; } @@ -121,7 +122,7 @@ mp_obj_t common_hal_socketpool_getaddrinfo_raise(socketpool_socketpool_obj_t *se }; struct addrinfo *res = NULL; - int err = getaddrinfo_common(host, port, &hints, &res); + int err = socketpool_getaddrinfo_common(host, port, &hints, &res); if (err != 0 || res == NULL) { common_hal_socketpool_socketpool_raise_gaierror_noname(); } diff --git a/ports/espressif/common-hal/socketpool/__init__.h b/ports/espressif/common-hal/socketpool/__init__.h index fd356b87050f..77ab155f69b7 100644 --- a/ports/espressif/common-hal/socketpool/__init__.h +++ b/ports/espressif/common-hal/socketpool/__init__.h @@ -6,8 +6,6 @@ #pragma once -#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_SOCKETPOOL___INIT___H -#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_SOCKETPOOL___INIT___H +struct addrinfo; - -#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_SOCKETPOOL___INIT___H +int socketpool_getaddrinfo_common(const char *host, int service, const struct addrinfo *hints, struct addrinfo **res); diff --git a/ports/espressif/common-hal/wifi/Radio.c b/ports/espressif/common-hal/wifi/Radio.c index c46630f92e7f..c065b7a2f078 100644 --- a/ports/espressif/common-hal/wifi/Radio.c +++ b/ports/espressif/common-hal/wifi/Radio.c @@ -13,6 +13,7 @@ #include "common-hal/wifi/__init__.h" #include "shared/runtime/interrupt_char.h" #include "py/gc.h" +#include "py/obj.h" #include "py/runtime.h" #include "shared-bindings/ipaddress/IPv4Address.h" #include "shared-bindings/wifi/ScannedNetworks.h" @@ -20,8 +21,14 @@ #include "shared-bindings/time/__init__.h" #include "shared-module/ipaddress/__init__.h" +#include "components/esp_netif/include/esp_netif_net_stack.h" #include "components/esp_wifi/include/esp_wifi.h" #include "components/lwip/include/apps/ping/ping_sock.h" +#include "lwip/sockets.h" + +#if LWIP_IPV6_DHCP6 +#include "lwip/dhcp6.h" +#endif #if CIRCUITPY_MDNS #include "common-hal/mdns/Server.h" @@ -445,6 +452,24 @@ mp_obj_t common_hal_wifi_radio_get_ipv4_subnet_ap(wifi_radio_obj_t *self) { return common_hal_ipaddress_new_ipv4address(self->ap_ip_info.netmask.addr); } +mp_obj_t common_hal_wifi_radio_get_ipv6_addresses(wifi_radio_obj_t *self) { + if (!esp_netif_is_netif_up(self->netif)) { + return mp_const_none; + } + esp_ip6_addr_t addresses[LWIP_IPV6_NUM_ADDRESSES]; + int n_addresses = esp_netif_get_all_ip6(self->netif, &addresses[0]); + if (!n_addresses) { + return mp_const_none; + } + mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_addresses, NULL)); + for (int i = 0; i < n_addresses; i++) { + char buf[IP6ADDR_STRLEN_MAX]; + inet_ntop(AF_INET6, &addresses[i], buf, sizeof(buf)); + result->items[i] = mp_obj_new_str(buf, strlen(buf)); + } + return MP_OBJ_FROM_PTR(result); +} + uint32_t wifi_radio_get_ipv4_address(wifi_radio_obj_t *self) { if (!esp_netif_is_netif_up(self->netif)) { return 0; @@ -491,10 +516,17 @@ void common_hal_wifi_radio_set_ipv4_dns(wifi_radio_obj_t *self, mp_obj_t ipv4_dn void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self) { esp_netif_dhcpc_start(self->netif); + #if LWIP_IPV6_DHCP6 + esp_netif_create_ip6_linklocal(self->netif); + dhcp6_enable_stateless(esp_netif_get_netif_impl(self->netif)); + #endif } void common_hal_wifi_radio_stop_dhcp_client(wifi_radio_obj_t *self) { esp_netif_dhcpc_stop(self->netif); + #if LWIP_IPV6_DHCP6 + dhcp6_disable(esp_netif_get_netif_impl(self->netif)); + #endif } void common_hal_wifi_radio_start_dhcp_server(wifi_radio_obj_t *self) { diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c index 76ae4345ab2d..d08f7640a36d 100644 --- a/shared-bindings/wifi/Radio.c +++ b/shared-bindings/wifi/Radio.c @@ -596,6 +596,22 @@ static mp_obj_t wifi_radio_set_ipv4_address_ap(size_t n_args, const mp_obj_t *po } static MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_set_ipv4_address_ap_obj, 1, wifi_radio_set_ipv4_address_ap); +//| ipv6_addresses: Sequence[str] +//| """IPv6 address(es) of the station when connected to an access point. None otherwise. (read-only)""" +static mp_obj_t _wifi_radio_get_ipv6_addresses(mp_obj_t self) { + return common_hal_wifi_radio_get_ipv6_addresses(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv6_addresses_obj, _wifi_radio_get_ipv6_addresses); + +MP_PROPERTY_GETTER(wifi_radio_ipv6_addresses_obj, + (mp_obj_t)&wifi_radio_get_ipv6_addresses_obj); + +#if 0 +MP_WEAK mp_obj_t common_hal_wifi_radio_get_ipv6_addresses(wifi_radio_obj_t *self) { + return mp_const_none; +} +#endif + //| ipv4_address: Optional[ipaddress.IPv4Address] //| """IP v4 Address of the station when connected to an access point. None otherwise. (read-only)""" static mp_obj_t _wifi_radio_get_ipv4_address(mp_obj_t self) { @@ -768,6 +784,7 @@ static const mp_rom_map_elem_t wifi_radio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ipv4_subnet_ap), MP_ROM_PTR(&wifi_radio_ipv4_subnet_ap_obj) }, { MP_ROM_QSTR(MP_QSTR_ipv4_address), MP_ROM_PTR(&wifi_radio_ipv4_address_obj) }, { MP_ROM_QSTR(MP_QSTR_ipv4_address_ap), MP_ROM_PTR(&wifi_radio_ipv4_address_ap_obj) }, + { MP_ROM_QSTR(MP_QSTR_ipv6_addresses), MP_ROM_PTR(&wifi_radio_ipv6_addresses_obj) }, { MP_ROM_QSTR(MP_QSTR_set_ipv4_address), MP_ROM_PTR(&wifi_radio_set_ipv4_address_obj) }, { MP_ROM_QSTR(MP_QSTR_set_ipv4_address_ap), MP_ROM_PTR(&wifi_radio_set_ipv4_address_ap_obj) }, diff --git a/shared-bindings/wifi/Radio.h b/shared-bindings/wifi/Radio.h index 6c39c5b1861a..87d6bd5d9159 100644 --- a/shared-bindings/wifi/Radio.h +++ b/shared-bindings/wifi/Radio.h @@ -105,6 +105,8 @@ uint32_t wifi_radio_get_ipv4_address(wifi_radio_obj_t *self); extern mp_obj_t common_hal_wifi_radio_get_ipv4_address(wifi_radio_obj_t *self); extern mp_obj_t common_hal_wifi_radio_get_ipv4_address_ap(wifi_radio_obj_t *self); +mp_obj_t common_hal_wifi_radio_get_ipv6_addresses(wifi_radio_obj_t *self); + extern void common_hal_wifi_radio_set_ipv4_address(wifi_radio_obj_t *self, mp_obj_t ipv4, mp_obj_t netmask, mp_obj_t gateway, mp_obj_t ipv4_dns_addr); extern void common_hal_wifi_radio_set_ipv4_address_ap(wifi_radio_obj_t *self, mp_obj_t ipv4, mp_obj_t netmask, mp_obj_t gateway); From 86f7a38ff41322658d4c729bac18987556cf2416 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 17 Jul 2024 12:08:13 -0500 Subject: [PATCH 05/18] Add wifi.radio.addresses, .addresses_ap, .dns --- .../espressif/common-hal/socketpool/Socket.c | 10 +++- .../common-hal/socketpool/__init__.h | 1 + ports/espressif/common-hal/wifi/Radio.c | 58 ++++++++++++++---- ports/espressif/common-hal/wifi/__init__.c | 60 +++++++++++++++++++ ports/espressif/common-hal/wifi/__init__.h | 9 +++ shared-bindings/wifi/Radio.c | 50 +++++++++++++--- shared-bindings/wifi/Radio.h | 6 +- 7 files changed, 170 insertions(+), 24 deletions(-) diff --git a/ports/espressif/common-hal/socketpool/Socket.c b/ports/espressif/common-hal/socketpool/Socket.c index ba81b7a16b98..c50ef2ef0b64 100644 --- a/ports/espressif/common-hal/socketpool/Socket.c +++ b/ports/espressif/common-hal/socketpool/Socket.c @@ -26,11 +26,11 @@ #include "components/lwip/lwip/src/include/lwip/netdb.h" #include "components/vfs/include/esp_vfs_eventfd.h" -static void resolve_host_or_throw(socketpool_socket_obj_t *self, const char *hostname, struct sockaddr_storage *addr, int port) { +void socketpool_resolve_host_or_throw(int family, int type, const char *hostname, struct sockaddr_storage *addr, int port) { struct addrinfo *result_i; const struct addrinfo hints = { - .ai_family = self->family, - .ai_socktype = self->type, + .ai_family = family, + .ai_socktype = type, }; int error = socketpool_getaddrinfo_common(hostname, port, &hints, &result_i); if (error != 0 || result_i == NULL) { @@ -40,6 +40,10 @@ static void resolve_host_or_throw(socketpool_socket_obj_t *self, const char *hos lwip_freeaddrinfo(result_i); } +static void resolve_host_or_throw(socketpool_socket_obj_t *self, const char *hostname, struct sockaddr_storage *addr, int port) { + socketpool_resolve_host_or_throw(self->family, self->type, hostname, addr, port); +} + StackType_t socket_select_stack[2 * configMINIMAL_STACK_SIZE]; /* Socket state table: diff --git a/ports/espressif/common-hal/socketpool/__init__.h b/ports/espressif/common-hal/socketpool/__init__.h index 77ab155f69b7..48773954fe59 100644 --- a/ports/espressif/common-hal/socketpool/__init__.h +++ b/ports/espressif/common-hal/socketpool/__init__.h @@ -9,3 +9,4 @@ struct addrinfo; int socketpool_getaddrinfo_common(const char *host, int service, const struct addrinfo *hints, struct addrinfo **res); +void socketpool_resolve_host_or_throw(int family, int type, const char *hostname, struct sockaddr_storage *addr, int port); diff --git a/ports/espressif/common-hal/wifi/Radio.c b/ports/espressif/common-hal/wifi/Radio.c index c065b7a2f078..a3ef977af636 100644 --- a/ports/espressif/common-hal/wifi/Radio.c +++ b/ports/espressif/common-hal/wifi/Radio.c @@ -20,6 +20,7 @@ #include "shared-bindings/wifi/AuthMode.h" #include "shared-bindings/time/__init__.h" #include "shared-module/ipaddress/__init__.h" +#include "common-hal/socketpool/__init__.h" #include "components/esp_netif/include/esp_netif_net_stack.h" #include "components/esp_wifi/include/esp_wifi.h" @@ -452,24 +453,38 @@ mp_obj_t common_hal_wifi_radio_get_ipv4_subnet_ap(wifi_radio_obj_t *self) { return common_hal_ipaddress_new_ipv4address(self->ap_ip_info.netmask.addr); } -mp_obj_t common_hal_wifi_radio_get_ipv6_addresses(wifi_radio_obj_t *self) { - if (!esp_netif_is_netif_up(self->netif)) { - return mp_const_none; +static mp_obj_t common_hal_wifi_radio_get_addresses_netif(wifi_radio_obj_t *self, esp_netif_t *netif) { + if (!esp_netif_is_netif_up(netif)) { + return mp_const_empty_tuple; } + esp_netif_ip_info_t ip_info; + esp_netif_get_ip_info(netif, &ip_info); + int n_addresses4 = ip_info.ip.addr != INADDR_NONE; + esp_ip6_addr_t addresses[LWIP_IPV6_NUM_ADDRESSES]; - int n_addresses = esp_netif_get_all_ip6(self->netif, &addresses[0]); - if (!n_addresses) { - return mp_const_none; - } + int n_addresses6 = esp_netif_get_all_ip6(netif, &addresses[0]); + int n_addresses = n_addresses4 + n_addresses6; + mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_addresses, NULL)); - for (int i = 0; i < n_addresses; i++) { - char buf[IP6ADDR_STRLEN_MAX]; - inet_ntop(AF_INET6, &addresses[i], buf, sizeof(buf)); - result->items[i] = mp_obj_new_str(buf, strlen(buf)); + for (int i = 0; i < n_addresses6; i++) { + result->items[i] = espaddr6_to_str(&addresses[i]); } + + if (n_addresses4) { + result->items[n_addresses6] = espaddr4_to_str(&ip_info.ip); + } + return MP_OBJ_FROM_PTR(result); } +mp_obj_t common_hal_wifi_radio_get_addresses(wifi_radio_obj_t *self) { + return common_hal_wifi_radio_get_addresses_netif(self, self->netif); +} + +mp_obj_t common_hal_wifi_radio_get_addresses_ap(wifi_radio_obj_t *self) { + return common_hal_wifi_radio_get_addresses_netif(self, self->ap_netif); +} + uint32_t wifi_radio_get_ipv4_address(wifi_radio_obj_t *self) { if (!esp_netif_is_netif_up(self->netif)) { return 0; @@ -501,6 +516,9 @@ mp_obj_t common_hal_wifi_radio_get_ipv4_dns(wifi_radio_obj_t *self) { esp_netif_get_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &self->dns_info); + if (self->dns_info.ip.type != ESP_IPADDR_TYPE_V4) { + return mp_const_none; + } // dns_info is of type esp_netif_dns_info_t, which is just ever so slightly // different than esp_netif_ip_info_t used for // common_hal_wifi_radio_get_ipv4_address (includes both ipv4 and 6), @@ -621,3 +639,21 @@ void common_hal_wifi_radio_gc_collect(wifi_radio_obj_t *self) { // Only bother to scan the actual object references. gc_collect_ptr(self->current_scan); } + +mp_obj_t common_hal_wifi_radio_get_dns(wifi_radio_obj_t *self) { + if (!esp_netif_is_netif_up(self->netif)) { + return mp_const_none; + } + + esp_netif_get_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &self->dns_info); + + return espaddr_to_str(&self->dns_info.ip); +} + +void common_hal_wifi_radio_set_dns(wifi_radio_obj_t *self, mp_obj_t dns_addr_obj) { + struct sockaddr_storage addr_storage; + socketpool_resolve_host_or_throw(AF_UNSPEC, SOCK_STREAM, mp_obj_str_get_str(dns_addr_obj), &addr_storage, 1); + esp_netif_dns_info_t dns_info; + sockaddr_to_espaddr(&addr_storage, &dns_info.ip); + esp_netif_set_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &dns_info); +} diff --git a/ports/espressif/common-hal/wifi/__init__.c b/ports/espressif/common-hal/wifi/__init__.c index ddebc41a9738..0f40e06d5662 100644 --- a/ports/espressif/common-hal/wifi/__init__.c +++ b/ports/espressif/common-hal/wifi/__init__.c @@ -27,6 +27,8 @@ wifi_radio_obj_t common_hal_wifi_radio_obj; #include "supervisor/port.h" #include "supervisor/workflow.h" +#include "lwip/sockets.h" + #if CIRCUITPY_STATUS_BAR #include "supervisor/shared/status_bar.h" #endif @@ -255,3 +257,61 @@ void ipaddress_ipaddress_to_esp_idf_ip4(mp_obj_t ip_address, esp_ip4_addr_t *esp void common_hal_wifi_gc_collect(void) { common_hal_wifi_radio_gc_collect(&common_hal_wifi_radio_obj); } + +static mp_obj_t espaddrx_to_str(const void *espaddr, uint8_t esptype) { + char buf[IPADDR_STRLEN_MAX]; + inet_ntop(esptype == ESP_IPADDR_TYPE_V6 ? AF_INET6 : AF_INET, espaddr, buf, sizeof(buf)); + return mp_obj_new_str(buf, strlen(buf)); +} + +mp_obj_t espaddr_to_str(const esp_ip_addr_t *espaddr) { + return espaddrx_to_str(espaddr, espaddr->type); +} + +mp_obj_t espaddr4_to_str(const esp_ip4_addr_t *espaddr) { + return espaddrx_to_str(espaddr, ESP_IPADDR_TYPE_V4); +} + +mp_obj_t espaddr6_to_str(const esp_ip6_addr_t *espaddr) { + return espaddrx_to_str(espaddr, ESP_IPADDR_TYPE_V6); +} + +mp_obj_t sockaddr_to_str(const struct sockaddr_storage *sockaddr) { + char buf[IPADDR_STRLEN_MAX]; + if (sockaddr->ss_family == AF_INET6) { + const struct sockaddr_in6 *addr6 = (const void *)sockaddr; + inet_ntop(AF_INET6, &addr6->sin6_addr, buf, sizeof(buf)); + } else { + const struct sockaddr_in *addr = (const void *)sockaddr; + inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)); + } + return mp_obj_new_str(buf, strlen(buf)); +} + +void sockaddr_to_espaddr(const struct sockaddr_storage *sockaddr, esp_ip_addr_t *espaddr) { + if (sockaddr->ss_family == AF_INET6) { + const struct sockaddr_in6 *addr6 = (const void *)sockaddr; + MP_STATIC_ASSERT(sizeof(espaddr->u_addr.ip6.addr) == sizeof(addr6->sin6_addr)); + memcpy(&espaddr->u_addr.ip6.addr, &addr6->sin6_addr, sizeof(espaddr->u_addr.ip6.addr)); + espaddr->u_addr.ip6.zone = addr6->sin6_scope_id; + espaddr->type = ESP_IPADDR_TYPE_V6; + } else { + const struct sockaddr_in *addr = (const void *)sockaddr; + MP_STATIC_ASSERT(sizeof(espaddr->u_addr.ip4.addr) == sizeof(addr->sin_addr)); + memcpy(&espaddr->u_addr.ip4.addr, &addr->sin_addr, sizeof(espaddr->u_addr.ip4.addr)); + espaddr->type = ESP_IPADDR_TYPE_V4; + } +} + +void espaddr_to_sockaddr(const esp_ip_addr_t *espaddr, struct sockaddr_storage *sockaddr, int port) { + if (espaddr->type == ESP_IPADDR_TYPE_V6) { + struct sockaddr_in6 *addr6 = (void *)sockaddr; + MP_STATIC_ASSERT(sizeof(espaddr->u_addr.ip6.addr) == sizeof(addr6->sin6_addr)); + memcpy(&addr6->sin6_addr, &espaddr->u_addr.ip6.addr, sizeof(espaddr->u_addr.ip6.addr)); + addr6->sin6_scope_id = espaddr->u_addr.ip6.zone; + } else { + struct sockaddr_in *addr = (void *)sockaddr; + MP_STATIC_ASSERT(sizeof(espaddr->u_addr.ip4.addr) == sizeof(addr->sin_addr)); + memcpy(&addr->sin_addr, &espaddr->u_addr.ip4.addr, sizeof(espaddr->u_addr.ip4.addr)); + } +} diff --git a/ports/espressif/common-hal/wifi/__init__.h b/ports/espressif/common-hal/wifi/__init__.h index 55a7fddbf448..e6b0a4d1cba3 100644 --- a/ports/espressif/common-hal/wifi/__init__.h +++ b/ports/espressif/common-hal/wifi/__init__.h @@ -11,7 +11,16 @@ #include "lwip/api.h" #include "components/esp_wifi/include/esp_wifi.h" +struct sockaddr_storage; + void wifi_reset(void); void ipaddress_ipaddress_to_esp_idf(mp_obj_t ip_address, ip_addr_t *esp_ip_address); void ipaddress_ipaddress_to_esp_idf_ip4(mp_obj_t ip_address, esp_ip4_addr_t *esp_ip_address); + +mp_obj_t sockaddr_to_str(const struct sockaddr_storage *addr); +mp_obj_t espaddr_to_str(const esp_ip_addr_t *espaddr); +mp_obj_t espaddr4_to_str(const esp_ip4_addr_t *espaddr); +mp_obj_t espaddr6_to_str(const esp_ip6_addr_t *espaddr); +void sockaddr_to_espaddr(const struct sockaddr_storage *sockaddr, esp_ip_addr_t *espaddr); +void espaddr_to_sockaddr(const esp_ip_addr_t *espaddr, struct sockaddr_storage *sockaddr, int port); diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c index d08f7640a36d..f68ad8315bfa 100644 --- a/shared-bindings/wifi/Radio.c +++ b/shared-bindings/wifi/Radio.c @@ -596,18 +596,29 @@ static mp_obj_t wifi_radio_set_ipv4_address_ap(size_t n_args, const mp_obj_t *po } static MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_set_ipv4_address_ap_obj, 1, wifi_radio_set_ipv4_address_ap); -//| ipv6_addresses: Sequence[str] -//| """IPv6 address(es) of the station when connected to an access point. None otherwise. (read-only)""" -static mp_obj_t _wifi_radio_get_ipv6_addresses(mp_obj_t self) { - return common_hal_wifi_radio_get_ipv6_addresses(self); +//| addresses: Sequence[str] +//| """Address(es) of the station when connected to an access point. Empty sequence when not connected. (read-only)""" +static mp_obj_t _wifi_radio_get_addresses(mp_obj_t self) { + return common_hal_wifi_radio_get_addresses(self); } -MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv6_addresses_obj, _wifi_radio_get_ipv6_addresses); +MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_addresses_obj, _wifi_radio_get_addresses); + +MP_PROPERTY_GETTER(wifi_radio_addresses_obj, + (mp_obj_t)&wifi_radio_get_addresses_obj); + +//| addresses_ap: Sequence[str] +//| """Address(es) of the access point when enabled. Empty sequence when disabled. (read-only)""" +static mp_obj_t _wifi_radio_get_addresses_ap(mp_obj_t self) { + return common_hal_wifi_radio_get_addresses_ap(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_addresses_ap_obj, _wifi_radio_get_addresses_ap); + +MP_PROPERTY_GETTER(wifi_radio_addresses_ap_obj, + (mp_obj_t)&wifi_radio_get_addresses_ap_obj); -MP_PROPERTY_GETTER(wifi_radio_ipv6_addresses_obj, - (mp_obj_t)&wifi_radio_get_ipv6_addresses_obj); #if 0 -MP_WEAK mp_obj_t common_hal_wifi_radio_get_ipv6_addresses(wifi_radio_obj_t *self) { +MP_WEAK mp_obj_t common_hal_wifi_radio_get_addresses(wifi_radio_obj_t *self) { return mp_const_none; } #endif @@ -650,6 +661,24 @@ MP_PROPERTY_GETSET(wifi_radio_ipv4_dns_obj, (mp_obj_t)&wifi_radio_get_ipv4_dns_obj, (mp_obj_t)&wifi_radio_set_ipv4_dns_obj); +//| dns: str +//| """Address of the DNS server to be used.""" +static mp_obj_t wifi_radio_get_dns(mp_obj_t self) { + return common_hal_wifi_radio_get_dns(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_dns_obj, wifi_radio_get_dns); + +static mp_obj_t wifi_radio_set_dns(mp_obj_t self, mp_obj_t dns_addr) { + common_hal_wifi_radio_set_dns(self, dns_addr); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(wifi_radio_set_dns_obj, wifi_radio_set_dns); + +MP_PROPERTY_GETSET(wifi_radio_dns_obj, + (mp_obj_t)&wifi_radio_get_dns_obj, + (mp_obj_t)&wifi_radio_set_dns_obj); + //| ap_info: Optional[Network] //| """Network object containing BSSID, SSID, authmode, channel, country and RSSI when connected to an access point. None otherwise.""" static mp_obj_t wifi_radio_get_ap_info(mp_obj_t self) { @@ -784,11 +813,14 @@ static const mp_rom_map_elem_t wifi_radio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ipv4_subnet_ap), MP_ROM_PTR(&wifi_radio_ipv4_subnet_ap_obj) }, { MP_ROM_QSTR(MP_QSTR_ipv4_address), MP_ROM_PTR(&wifi_radio_ipv4_address_obj) }, { MP_ROM_QSTR(MP_QSTR_ipv4_address_ap), MP_ROM_PTR(&wifi_radio_ipv4_address_ap_obj) }, - { MP_ROM_QSTR(MP_QSTR_ipv6_addresses), MP_ROM_PTR(&wifi_radio_ipv6_addresses_obj) }, { MP_ROM_QSTR(MP_QSTR_set_ipv4_address), MP_ROM_PTR(&wifi_radio_set_ipv4_address_obj) }, { MP_ROM_QSTR(MP_QSTR_set_ipv4_address_ap), MP_ROM_PTR(&wifi_radio_set_ipv4_address_ap_obj) }, + { MP_ROM_QSTR(MP_QSTR_addresses), MP_ROM_PTR(&wifi_radio_addresses_obj) }, + { MP_ROM_QSTR(MP_QSTR_addresses_ap), MP_ROM_PTR(&wifi_radio_addresses_ap_obj) }, + { MP_ROM_QSTR(MP_QSTR_dns), MP_ROM_PTR(&wifi_radio_dns_obj) }, + { MP_ROM_QSTR(MP_QSTR_ping), MP_ROM_PTR(&wifi_radio_ping_obj) }, }; diff --git a/shared-bindings/wifi/Radio.h b/shared-bindings/wifi/Radio.h index 87d6bd5d9159..e8527c3f8a09 100644 --- a/shared-bindings/wifi/Radio.h +++ b/shared-bindings/wifi/Radio.h @@ -105,7 +105,11 @@ uint32_t wifi_radio_get_ipv4_address(wifi_radio_obj_t *self); extern mp_obj_t common_hal_wifi_radio_get_ipv4_address(wifi_radio_obj_t *self); extern mp_obj_t common_hal_wifi_radio_get_ipv4_address_ap(wifi_radio_obj_t *self); -mp_obj_t common_hal_wifi_radio_get_ipv6_addresses(wifi_radio_obj_t *self); +mp_obj_t common_hal_wifi_radio_get_addresses(wifi_radio_obj_t *self); +mp_obj_t common_hal_wifi_radio_get_addresses_ap(wifi_radio_obj_t *self); + +extern mp_obj_t common_hal_wifi_radio_get_dns(wifi_radio_obj_t *self); +extern void common_hal_wifi_radio_set_dns(wifi_radio_obj_t *self, mp_obj_t dns_addr); extern void common_hal_wifi_radio_set_ipv4_address(wifi_radio_obj_t *self, mp_obj_t ipv4, mp_obj_t netmask, mp_obj_t gateway, mp_obj_t ipv4_dns_addr); extern void common_hal_wifi_radio_set_ipv4_address_ap(wifi_radio_obj_t *self, mp_obj_t ipv4, mp_obj_t netmask, mp_obj_t gateway); From 524236dc0afadf2c61ca517f9ae515512b84e81e Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 17 Jul 2024 13:23:47 -0500 Subject: [PATCH 06/18] v6 ping works. --- ports/espressif/common-hal/wifi/Radio.c | 4 ++-- ports/espressif/common-hal/wifi/__init__.c | 23 +++++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/ports/espressif/common-hal/wifi/Radio.c b/ports/espressif/common-hal/wifi/Radio.c index a3ef977af636..cdea302b6e19 100644 --- a/ports/espressif/common-hal/wifi/Radio.c +++ b/ports/espressif/common-hal/wifi/Radio.c @@ -618,11 +618,11 @@ mp_int_t common_hal_wifi_radio_ping(wifi_radio_obj_t *self, mp_obj_t ip_address, CHECK_ESP_RESULT(esp_ping_new_session(&ping_config, &ping_callbacks, &ping)); } - esp_ping_start(ping); - // Use all ones as a flag that the elapsed time was not set (ping failed or timed out). self->ping_elapsed_time = (uint32_t)(-1); + esp_ping_start(ping); + uint32_t start_time = common_hal_time_monotonic_ms(); while ((self->ping_elapsed_time == (uint32_t)(-1)) && (common_hal_time_monotonic_ms() - start_time < timeout_ms) && diff --git a/ports/espressif/common-hal/wifi/__init__.c b/ports/espressif/common-hal/wifi/__init__.c index 0f40e06d5662..549d132ee09d 100644 --- a/ports/espressif/common-hal/wifi/__init__.c +++ b/ports/espressif/common-hal/wifi/__init__.c @@ -11,6 +11,7 @@ #include "shared-bindings/ipaddress/IPv4Address.h" #include "shared-bindings/wifi/Monitor.h" #include "shared-bindings/wifi/Radio.h" +#include "common-hal/socketpool/__init__.h" #include "py/gc.h" #include "py/mpstate.h" @@ -234,14 +235,14 @@ void wifi_reset(void) { } void ipaddress_ipaddress_to_esp_idf(mp_obj_t ip_address, ip_addr_t *esp_ip_address) { - if (!mp_obj_is_type(ip_address, &ipaddress_ipv4address_type)) { - mp_raise_ValueError(MP_ERROR_TEXT("Only IPv4 addresses supported")); + if (mp_obj_is_type(ip_address, &ipaddress_ipv4address_type)) { + ipaddress_ipaddress_to_esp_idf_ip4(ip_address, (esp_ip4_addr_t *)esp_ip_address); + esp_ip_address->type = IPADDR_TYPE_V4; + } else { + struct sockaddr_storage addr_storage; + socketpool_resolve_host_or_throw(AF_UNSPEC, SOCK_STREAM, mp_obj_str_get_str(ip_address), &addr_storage, 1); + sockaddr_to_espaddr(&addr_storage, (esp_ip_addr_t *)esp_ip_address); } - mp_obj_t packed = common_hal_ipaddress_ipv4address_get_packed(ip_address); - size_t len; - const char *bytes = mp_obj_str_get_data(packed, &len); - - IP_ADDR4(esp_ip_address, bytes[0], bytes[1], bytes[2], bytes[3]); } void ipaddress_ipaddress_to_esp_idf_ip4(mp_obj_t ip_address, esp_ip4_addr_t *esp_ip_address) { @@ -288,7 +289,13 @@ mp_obj_t sockaddr_to_str(const struct sockaddr_storage *sockaddr) { return mp_obj_new_str(buf, strlen(buf)); } + void sockaddr_to_espaddr(const struct sockaddr_storage *sockaddr, esp_ip_addr_t *espaddr) { + MP_STATIC_ASSERT(IPADDR_TYPE_V4 == ESP_IPADDR_TYPE_V4); + MP_STATIC_ASSERT(IPADDR_TYPE_V6 == ESP_IPADDR_TYPE_V6); + MP_STATIC_ASSERT(sizeof(ip_addr_t) == sizeof(esp_ip_addr_t)); + MP_STATIC_ASSERT(offsetof(ip_addr_t, u_addr) == offsetof(esp_ip_addr_t, u_addr)); + MP_STATIC_ASSERT(offsetof(ip_addr_t, type) == offsetof(esp_ip_addr_t, type)); if (sockaddr->ss_family == AF_INET6) { const struct sockaddr_in6 *addr6 = (const void *)sockaddr; MP_STATIC_ASSERT(sizeof(espaddr->u_addr.ip6.addr) == sizeof(addr6->sin6_addr)); @@ -306,12 +313,10 @@ void sockaddr_to_espaddr(const struct sockaddr_storage *sockaddr, esp_ip_addr_t void espaddr_to_sockaddr(const esp_ip_addr_t *espaddr, struct sockaddr_storage *sockaddr, int port) { if (espaddr->type == ESP_IPADDR_TYPE_V6) { struct sockaddr_in6 *addr6 = (void *)sockaddr; - MP_STATIC_ASSERT(sizeof(espaddr->u_addr.ip6.addr) == sizeof(addr6->sin6_addr)); memcpy(&addr6->sin6_addr, &espaddr->u_addr.ip6.addr, sizeof(espaddr->u_addr.ip6.addr)); addr6->sin6_scope_id = espaddr->u_addr.ip6.zone; } else { struct sockaddr_in *addr = (void *)sockaddr; - MP_STATIC_ASSERT(sizeof(espaddr->u_addr.ip4.addr) == sizeof(addr->sin_addr)); memcpy(&addr->sin_addr, &espaddr->u_addr.ip4.addr, sizeof(espaddr->u_addr.ip4.addr)); } } From bee32ea826560f2347aa75ce6316626235715490 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 17 Jul 2024 17:15:22 -0500 Subject: [PATCH 07/18] Make return value of recvfrom_into & accept right for v6 addresses only tested recvfrom_into as can't bind() v6 addresses yet wifi workflow may be broken by this or maybe it was broken before --- .../espressif/common-hal/socketpool/Socket.c | 39 ++++++++++--------- ports/espressif/common-hal/wifi/__init__.c | 17 ++++++++ ports/espressif/common-hal/wifi/__init__.h | 1 + shared-bindings/socketpool/Socket.c | 16 ++------ shared-bindings/socketpool/Socket.h | 6 +-- supervisor/shared/web_workflow/web_workflow.c | 4 +- 6 files changed, 47 insertions(+), 36 deletions(-) diff --git a/ports/espressif/common-hal/socketpool/Socket.c b/ports/espressif/common-hal/socketpool/Socket.c index c50ef2ef0b64..60ed9a1196e6 100644 --- a/ports/espressif/common-hal/socketpool/Socket.c +++ b/ports/espressif/common-hal/socketpool/Socket.c @@ -12,6 +12,7 @@ #include "py/runtime.h" #include "shared-bindings/socketpool/SocketPool.h" #include "common-hal/socketpool/__init__.h" +#include "common-hal/wifi/__init__.h" #if CIRCUITPY_SSL #include "shared-bindings/ssl/SSLSocket.h" #include "shared-module/ssl/SSLSocket.h" @@ -269,9 +270,9 @@ socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_ return sock; } -int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_t *port, socketpool_socket_obj_t *accepted) { - struct sockaddr_in accept_addr; - socklen_t socklen = sizeof(accept_addr); +int socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out, socketpool_socket_obj_t *accepted) { + struct sockaddr_storage peer_addr; + socklen_t socklen = sizeof(peer_addr); int newsoc = -1; bool timed_out = false; uint64_t start_ticks = supervisor_ticks_ms64(); @@ -282,20 +283,17 @@ int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_ timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms; } RUN_BACKGROUND_TASKS; - newsoc = lwip_accept(self->num, (struct sockaddr *)&accept_addr, &socklen); + newsoc = lwip_accept(self->num, (struct sockaddr *)&peer_addr, &socklen); // In non-blocking mode, fail instead of timing out if (newsoc == -1 && (self->timeout_ms == 0 || mp_hal_is_interrupted())) { return -MP_EAGAIN; } } - if (!timed_out) { - // harmless on failure but avoiding memcpy is faster - memcpy((void *)ip, (void *)&accept_addr.sin_addr.s_addr, sizeof(accept_addr.sin_addr.s_addr)); - *port = accept_addr.sin_port; - } else { + if (timed_out) { return -ETIMEDOUT; } + if (newsoc < 0) { return -MP_EBADF; } @@ -320,13 +318,16 @@ int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_ accepted->type = self->type; } + if (peer_out) { + *peer_out = sockaddr_to_tuple(&peer_addr); + } + return newsoc; } -socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *self, - uint8_t *ip, uint32_t *port) { +socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out) { socketpool_socket_obj_t *sock = m_new_obj_with_finaliser(socketpool_socket_obj_t); - int newsoc = socketpool_socket_accept(self, ip, port, NULL); + int newsoc = socketpool_socket_accept(self, peer_out, NULL); if (newsoc > 0) { // Create the socket @@ -344,6 +345,7 @@ socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_o } } +// TODO: ipv6 size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self, const char *host, size_t hostlen, uint32_t port) { struct sockaddr_in bind_addr; @@ -490,9 +492,9 @@ bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *self, int back } mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *self, - uint8_t *buf, uint32_t len, uint8_t *ip, uint32_t *port) { + uint8_t *buf, uint32_t len, mp_obj_t *source_out) { - struct sockaddr_in source_addr; + struct sockaddr_storage source_addr; socklen_t socklen = sizeof(source_addr); // LWIP Socket @@ -514,10 +516,7 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *se } } - if (!timed_out) { - memcpy((void *)ip, (void *)&source_addr.sin_addr.s_addr, sizeof(source_addr.sin_addr.s_addr)); - *port = htons(source_addr.sin_port); - } else { + if (timed_out) { mp_raise_OSError(ETIMEDOUT); } @@ -526,6 +525,10 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *se return 0; } + if (source_out) { + *source_out = sockaddr_to_tuple(&source_addr); + } + return received; } diff --git a/ports/espressif/common-hal/wifi/__init__.c b/ports/espressif/common-hal/wifi/__init__.c index 549d132ee09d..b005d8993e78 100644 --- a/ports/espressif/common-hal/wifi/__init__.c +++ b/ports/espressif/common-hal/wifi/__init__.c @@ -289,6 +289,23 @@ mp_obj_t sockaddr_to_str(const struct sockaddr_storage *sockaddr) { return mp_obj_new_str(buf, strlen(buf)); } +mp_obj_t sockaddr_to_tuple(const struct sockaddr_storage *sockaddr) { + mp_obj_t args[4] = { + sockaddr_to_str(sockaddr), + }; + int n = 2; + if (sockaddr->ss_family == AF_INET6) { + const struct sockaddr_in6 *addr6 = (const void *)sockaddr; + args[1] = MP_OBJ_NEW_SMALL_INT(htons(addr6->sin6_port)); + args[2] = MP_OBJ_NEW_SMALL_INT(addr6->sin6_flowinfo); + args[3] = MP_OBJ_NEW_SMALL_INT(addr6->sin6_scope_id); + n = 4; + } else { + const struct sockaddr_in *addr = (const void *)sockaddr; + args[1] = MP_OBJ_NEW_SMALL_INT(htons(addr->sin_port)); + } + return mp_obj_new_tuple(n, args); +} void sockaddr_to_espaddr(const struct sockaddr_storage *sockaddr, esp_ip_addr_t *espaddr) { MP_STATIC_ASSERT(IPADDR_TYPE_V4 == ESP_IPADDR_TYPE_V4); diff --git a/ports/espressif/common-hal/wifi/__init__.h b/ports/espressif/common-hal/wifi/__init__.h index e6b0a4d1cba3..cbd3c000a179 100644 --- a/ports/espressif/common-hal/wifi/__init__.h +++ b/ports/espressif/common-hal/wifi/__init__.h @@ -19,6 +19,7 @@ void ipaddress_ipaddress_to_esp_idf(mp_obj_t ip_address, ip_addr_t *esp_ip_addre void ipaddress_ipaddress_to_esp_idf_ip4(mp_obj_t ip_address, esp_ip4_addr_t *esp_ip_address); mp_obj_t sockaddr_to_str(const struct sockaddr_storage *addr); +mp_obj_t sockaddr_to_tuple(const struct sockaddr_storage *addr); mp_obj_t espaddr_to_str(const esp_ip_addr_t *espaddr); mp_obj_t espaddr4_to_str(const esp_ip4_addr_t *espaddr); mp_obj_t espaddr6_to_str(const esp_ip6_addr_t *espaddr); diff --git a/shared-bindings/socketpool/Socket.c b/shared-bindings/socketpool/Socket.c index dfc3c98f4374..25d10c294827 100644 --- a/shared-bindings/socketpool/Socket.c +++ b/shared-bindings/socketpool/Socket.c @@ -57,14 +57,10 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socketpool_socket___exit___obj, 4, 4, //| Returns a tuple of (new_socket, remote_address)""" static mp_obj_t _socketpool_socket_accept(mp_obj_t self_in) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); - uint8_t ip[4]; - uint32_t port; - - socketpool_socket_obj_t *sock = common_hal_socketpool_socket_accept(self, ip, &port); mp_obj_t tuple_contents[2]; - tuple_contents[0] = MP_OBJ_FROM_PTR(sock); - tuple_contents[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); + tuple_contents[0] = MP_OBJ_FROM_PTR(common_hal_socketpool_socket_accept(self, &tuple_contents[1])); + return mp_obj_new_tuple(2, tuple_contents); } static MP_DEFINE_CONST_FUN_OBJ_1(socketpool_socket_accept_obj, _socketpool_socket_accept); @@ -158,13 +154,9 @@ static mp_obj_t socketpool_socket_recvfrom_into(mp_obj_t self_in, mp_obj_t data_ mp_buffer_info_t bufinfo; mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_WRITE); - byte ip[4]; - uint32_t port; - mp_int_t ret = common_hal_socketpool_socket_recvfrom_into(self, - (byte *)bufinfo.buf, bufinfo.len, ip, &port); mp_obj_t tuple_contents[2]; - tuple_contents[0] = mp_obj_new_int_from_uint(ret); - tuple_contents[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); + tuple_contents[0] = mp_obj_new_int_from_uint(common_hal_socketpool_socket_recvfrom_into(self, + (byte *)bufinfo.buf, bufinfo.len, &tuple_contents[1])); return mp_obj_new_tuple(2, tuple_contents); } static MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_recvfrom_into_obj, socketpool_socket_recvfrom_into); diff --git a/shared-bindings/socketpool/Socket.h b/shared-bindings/socketpool/Socket.h index 25ba7ecff558..a883ebd50546 100644 --- a/shared-bindings/socketpool/Socket.h +++ b/shared-bindings/socketpool/Socket.h @@ -10,7 +10,7 @@ extern const mp_obj_type_t socketpool_socket_type; -socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_t *port); +socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out); size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self, const char *host, size_t hostlen, uint32_t port); void common_hal_socketpool_socket_close(socketpool_socket_obj_t *self); void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self, const char *host, size_t hostlen, uint32_t port); @@ -20,7 +20,7 @@ mp_uint_t common_hal_socketpool_socket_get_timeout(socketpool_socket_obj_t *self mp_int_t common_hal_socketpool_socket_get_type(socketpool_socket_obj_t *self); bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *self, int backlog); mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *self, - uint8_t *buf, uint32_t len, uint8_t *ip, uint32_t *port); + uint8_t *buf, uint32_t len, mp_obj_t *peer_out); mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len); mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len); mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *self, @@ -31,7 +31,7 @@ bool common_hal_socketpool_readable(socketpool_socket_obj_t *self); bool common_hal_socketpool_writable(socketpool_socket_obj_t *self); // Non-allocating versions for internal use. -int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_t *port, socketpool_socket_obj_t *accepted); +int socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out, socketpool_socket_obj_t *accepted); void socketpool_socket_close(socketpool_socket_obj_t *self); int socketpool_socket_send(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len); int socketpool_socket_recv_into(socketpool_socket_obj_t *self, diff --git a/supervisor/shared/web_workflow/web_workflow.c b/supervisor/shared/web_workflow/web_workflow.c index 8cb9237f5af2..6d18172b3e4d 100644 --- a/supervisor/shared/web_workflow/web_workflow.c +++ b/supervisor/shared/web_workflow/web_workflow.c @@ -1592,12 +1592,10 @@ void supervisor_web_workflow_background(void *data) { if ((!common_hal_socketpool_socket_get_connected(&active) || (!active_request.in_progress && !active_request.new_socket)) && !common_hal_socketpool_socket_get_closed(&listening)) { - uint32_t ip; - uint32_t port; if (!common_hal_socketpool_socket_get_closed(&active)) { common_hal_socketpool_socket_close(&active); } - int newsoc = socketpool_socket_accept(&listening, (uint8_t *)&ip, &port, &active); + int newsoc = socketpool_socket_accept(&listening, NULL, &active); if (newsoc == -EBADF) { common_hal_socketpool_socket_close(&listening); break; From 2385aa6dfbe02bab6e55ff79c392a59dc94f030d Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 17 Jul 2024 18:00:04 -0500 Subject: [PATCH 08/18] Fix socket binding .. & make web workflow bind to v6 if available. Binding v6 "any" address also allows v4 connections --- .../espressif/common-hal/socketpool/Socket.c | 34 +++++++++++++------ supervisor/shared/web_workflow/web_workflow.c | 4 +++ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/ports/espressif/common-hal/socketpool/Socket.c b/ports/espressif/common-hal/socketpool/Socket.c index 60ed9a1196e6..14649e63c909 100644 --- a/ports/espressif/common-hal/socketpool/Socket.c +++ b/ports/espressif/common-hal/socketpool/Socket.c @@ -348,20 +348,32 @@ socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_o // TODO: ipv6 size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self, const char *host, size_t hostlen, uint32_t port) { - struct sockaddr_in bind_addr; + struct sockaddr_storage bind_addr; const char *broadcast = ""; - uint32_t ip; - if (hostlen == 0) { - ip = IPADDR_ANY; - } else if (hostlen == strlen(broadcast) && - memcmp(host, broadcast, strlen(broadcast)) == 0) { - ip = IPADDR_BROADCAST; + + bind_addr.ss_family = self->family; + + if (self->family == AF_INET6) { + struct sockaddr_in6 *addr6 = (void *)&bind_addr; + addr6->sin6_port = htons(port); + // no ipv6 broadcast + if (hostlen == 0) { + memset(&addr6->sin6_addr, 0, sizeof(addr6->sin6_addr)); + } else { + socketpool_resolve_host_or_throw(self->family, self->type, host, &bind_addr, port); + } } else { - ip = inet_addr(host); + struct sockaddr_in *addr4 = (void *)&bind_addr; + addr4->sin_port = htons(port); + if (hostlen == 0) { + addr4->sin_addr.s_addr = IPADDR_ANY; + } else if (hostlen == strlen(broadcast) && + memcmp(host, broadcast, strlen(broadcast)) == 0) { + addr4->sin_addr.s_addr = IPADDR_BROADCAST; + } else { + socketpool_resolve_host_or_throw(self->family, self->type, host, &bind_addr, port); + } } - bind_addr.sin_addr.s_addr = ip; - bind_addr.sin_family = self->family; - bind_addr.sin_port = htons(port); int result = lwip_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr)); if (result == 0) { diff --git a/supervisor/shared/web_workflow/web_workflow.c b/supervisor/shared/web_workflow/web_workflow.c index 6d18172b3e4d..45d3c21163ac 100644 --- a/supervisor/shared/web_workflow/web_workflow.c +++ b/supervisor/shared/web_workflow/web_workflow.c @@ -338,7 +338,11 @@ bool supervisor_start_web_workflow(void) { #endif if (common_hal_socketpool_socket_get_closed(&listening)) { + #if CIRCUITPY_SOCKETPOOL_IPV6 + socketpool_socket(&pool, SOCKETPOOL_AF_INET6, SOCKETPOOL_SOCK_STREAM, 0, &listening); + #else socketpool_socket(&pool, SOCKETPOOL_AF_INET, SOCKETPOOL_SOCK_STREAM, 0, &listening); + #endif common_hal_socketpool_socket_settimeout(&listening, 0); // Bind to any ip. (Not checking for failures) common_hal_socketpool_socket_bind(&listening, "", 0, web_api_port); From e5e4b0c61cf010aa2816a8050b996ea707580a24 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 19 Jul 2024 12:19:26 -0500 Subject: [PATCH 09/18] Implement new routines in raspberrypi port --- .../common-hal/socketpool/Socket.c | 70 ++++++++++++++----- .../common-hal/socketpool/Socket.h | 2 +- .../common-hal/socketpool/SocketPool.c | 65 +---------------- .../common-hal/socketpool/SocketPool.h | 2 - .../common-hal/socketpool/__init__.c | 70 ++++++++++++++++++- .../common-hal/socketpool/__init__.h | 5 ++ ports/raspberrypi/common-hal/wifi/Radio.c | 38 ++++++++++ 7 files changed, 167 insertions(+), 85 deletions(-) diff --git a/ports/raspberrypi/common-hal/socketpool/Socket.c b/ports/raspberrypi/common-hal/socketpool/Socket.c index b71d519b14c2..d2626456f950 100644 --- a/ports/raspberrypi/common-hal/socketpool/Socket.c +++ b/ports/raspberrypi/common-hal/socketpool/Socket.c @@ -21,6 +21,7 @@ #include "supervisor/port.h" #include "supervisor/shared/tick.h" #include "supervisor/workflow.h" +#include "common-hal/socketpool/__init__.h" #include "lwip/dns.h" #include "lwip/err.h" @@ -36,6 +37,36 @@ #include "sdk/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch.h" +mp_obj_t socketpool_ip_addr_to_str(const ip_addr_t *addr) { + char ip_str[IPADDR_STRLEN_MAX]; // big enough for any supported address type + switch (IP_GET_TYPE(addr)) { + #if CIRCUITPY_SOCKETPOOL_IPV6 + case IPADDR_TYPE_V6: + ip6addr_ntoa_r(ip_2_ip6(addr), ip_str, sizeof(ip_str)); + break; + #endif + default: + ip4addr_ntoa_r(ip_2_ip4(addr), ip_str, sizeof(ip_str)); + } + return mp_obj_new_str(ip_str, strlen(ip_str)); +} + +static mp_obj_t socketpool_ip_addr_and_port_to_tuple(const ip_addr_t *addr, int port) { + mp_obj_t args[CIRCUITPY_SOCKETPOOL_IPV6 ? 4 : 2] = { + socketpool_ip_addr_to_str(addr), + MP_OBJ_NEW_SMALL_INT(port), + }; + int n = 2; + #if CIRCUITPY_SOCKETPOOL_IPV6 + if (IP_GET_TYPE(addr) == IPADDR_TYPE_V6) { + items[2] = MP_OBJ_NEW_SMALL_INT(0); // sin6_flowinfo + items[3] = MP_OBJ_NEW_SMALL_INT(ip_2_ip6(addr)->zone); + n = 4; + } + #endif + return mp_obj_new_tuple(n, args); +} + #define MICROPY_PY_LWIP_SOCK_RAW (1) #if 0 // print debugging info @@ -380,7 +411,7 @@ static mp_uint_t lwip_raw_udp_send(socketpool_socket_obj_t *socket, const byte * } // Helper function for recv/recvfrom to handle raw/UDP packets -static mp_uint_t lwip_raw_udp_receive(socketpool_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, uint32_t *port, int *_errno) { +static mp_uint_t lwip_raw_udp_receive(socketpool_socket_obj_t *socket, byte *buf, mp_uint_t len, mp_obj_t *peer_out, int *_errno) { if (socket->incoming.pbuf == NULL) { if (socket->timeout == 0) { @@ -400,9 +431,8 @@ static mp_uint_t lwip_raw_udp_receive(socketpool_socket_obj_t *socket, byte *buf } } - if (ip != NULL) { - memcpy(ip, &socket->peer, sizeof(socket->peer)); - *port = socket->peer_port; + if (peer_out != NULL) { + *peer_out = socketpool_ip_addr_and_port_to_tuple(&socket->peer, socket->peer_port); } struct pbuf *p = socket->incoming.pbuf; @@ -726,7 +756,7 @@ socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_ return socket; } -int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_t *port, socketpool_socket_obj_t *accepted) { +int socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out, socketpool_socket_obj_t *accepted) { if (self->type != MOD_NETWORK_SOCK_STREAM) { return -MP_EOPNOTSUPP; } @@ -808,20 +838,21 @@ int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_ MICROPY_PY_LWIP_EXIT // output values - memcpy(ip, &(accepted->pcb.tcp->remote_ip), NETUTILS_IPV4ADDR_BUFSIZE); - *port = (mp_uint_t)accepted->pcb.tcp->remote_port; + if (peer_out) { + *peer_out = socketpool_ip_addr_and_port_to_tuple(&accepted->pcb.tcp->remote_ip, accepted->pcb.tcp->remote_port); + } return 1; } socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *socket, - uint8_t *ip, uint32_t *port) { + mp_obj_t *peer_out) { // Create new socket object, do it here because we must not raise an out-of-memory // exception when the LWIP concurrency lock is held socketpool_socket_obj_t *accepted = m_new_ll_obj_with_finaliser(socketpool_socket_obj_t); socketpool_socket_reset(accepted); - int ret = socketpool_socket_accept(socket, ip, port, accepted); + int ret = socketpool_socket_accept(socket, peer_out, accepted); if (ret <= 0) { m_del_obj(socketpool_socket_obj_t, accepted); @@ -852,7 +883,7 @@ size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *socket, ip_addr_t bind_addr; const ip_addr_t *bind_addr_ptr = &bind_addr; if (hostlen > 0) { - socketpool_resolve_host_raise(socket->pool, host, &bind_addr); + socketpool_resolve_host_raise(host, &bind_addr); } else { bind_addr_ptr = IP_ANY_TYPE; } @@ -941,7 +972,7 @@ void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *socket, // get address ip_addr_t dest; - socketpool_resolve_host_raise(socket->pool, host, &dest); + socketpool_resolve_host_raise(host, &dest); err_t err = ERR_ARG; switch (socket->type) { @@ -966,7 +997,7 @@ void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *socket, mp_raise_OSError(error_lookup_table[-err]); } socket->peer_port = (mp_uint_t)port; - memcpy(socket->peer, &dest, sizeof(socket->peer)); + memcpy(&socket->peer, &dest, sizeof(socket->peer)); MICROPY_PY_LWIP_EXIT // And now we wait... @@ -1054,14 +1085,17 @@ bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *socket, int ba } mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *socket, - uint8_t *buf, uint32_t len, uint8_t *ip, uint32_t *port) { + uint8_t *buf, uint32_t len, mp_obj_t *peer_out) { int _errno; mp_uint_t ret = 0; switch (socket->type) { case SOCKETPOOL_SOCK_STREAM: { - memcpy(ip, &socket->peer, sizeof(socket->peer)); - *port = (mp_uint_t)socket->peer_port; + // output values + if (peer_out) { + *peer_out = socketpool_ip_addr_and_port_to_tuple(&socket->peer, socket->peer_port); + } + ret = lwip_tcp_receive(socket, (byte *)buf, len, &_errno); break; } @@ -1069,7 +1103,7 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *so #if MICROPY_PY_LWIP_SOCK_RAW case SOCKETPOOL_SOCK_RAW: #endif - ret = lwip_raw_udp_receive(socket, (byte *)buf, len, ip, port, &_errno); + ret = lwip_raw_udp_receive(socket, (byte *)buf, len, peer_out, &_errno); break; } if (ret == (unsigned)-1) { @@ -1092,7 +1126,7 @@ int socketpool_socket_recv_into(socketpool_socket_obj_t *socket, #if MICROPY_PY_LWIP_SOCK_RAW case SOCKETPOOL_SOCK_RAW: #endif - ret = lwip_raw_udp_receive(socket, (byte *)buf, len, NULL, NULL, &_errno); + ret = lwip_raw_udp_receive(socket, (byte *)buf, len, NULL, &_errno); break; } if (ret == (unsigned)-1) { @@ -1143,7 +1177,7 @@ mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *socket, const char *host, size_t hostlen, uint32_t port, const uint8_t *buf, uint32_t len) { int _errno; ip_addr_t ip; - socketpool_resolve_host_raise(socket->pool, host, &ip); + socketpool_resolve_host_raise(host, &ip); mp_uint_t ret = 0; switch (socket->type) { diff --git a/ports/raspberrypi/common-hal/socketpool/Socket.h b/ports/raspberrypi/common-hal/socketpool/Socket.h index 62754a012115..d78987777448 100644 --- a/ports/raspberrypi/common-hal/socketpool/Socket.h +++ b/ports/raspberrypi/common-hal/socketpool/Socket.h @@ -35,7 +35,7 @@ typedef struct _lwip_socket_obj_t { } connection; } incoming; mp_obj_t callback; - byte peer[4]; + ip_addr_t peer; mp_uint_t peer_port; mp_uint_t timeout; uint16_t recv_offset; diff --git a/ports/raspberrypi/common-hal/socketpool/SocketPool.c b/ports/raspberrypi/common-hal/socketpool/SocketPool.c index cf92a622a1c7..200967ca6eb2 100644 --- a/ports/raspberrypi/common-hal/socketpool/SocketPool.c +++ b/ports/raspberrypi/common-hal/socketpool/SocketPool.c @@ -5,6 +5,7 @@ // SPDX-License-Identifier: MIT #include "shared-bindings/socketpool/SocketPool.h" +#include "common-hal/socketpool/__init__.h" #include "common-hal/socketpool/Socket.h" #include "shared/runtime/interrupt_char.h" #include "py/runtime.h" @@ -21,72 +22,10 @@ void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *sel // common_hal_socketpool_socket is in socketpool/Socket.c to centralize open socket tracking. -typedef struct _getaddrinfo_state_t { - volatile int status; - volatile ip_addr_t ipaddr; -} getaddrinfo_state_t; - -static void lwip_getaddrinfo_cb(const char *name, const ip_addr_t *ipaddr, void *arg) { - getaddrinfo_state_t *state = arg; - if (ipaddr != NULL) { - state->status = 1; - state->ipaddr = *ipaddr; - } else { - // error - state->status = -2; - } -} - -static int socketpool_resolve_host(socketpool_socketpool_obj_t *self, const char *host, ip_addr_t *addr) { - - getaddrinfo_state_t state; - state.status = 0; - - MICROPY_PY_LWIP_ENTER - err_t ret = dns_gethostbyname(host, (ip_addr_t *)&state.ipaddr, lwip_getaddrinfo_cb, &state); - MICROPY_PY_LWIP_EXIT - - switch (ret) { - case ERR_OK: - // cached - state.status = 1; - break; - case ERR_INPROGRESS: - while (state.status == 0) { - RUN_BACKGROUND_TASKS; - if (mp_hal_is_interrupted()) { - break; - } - } - break; - default: - state.status = ret; - } - - if (state.status < 0) { - return state.status; - // TODO: CPython raises gaierror, we raise with native lwIP negative error - // values, to differentiate from normal errno's at least in such way. - mp_raise_OSError(state.status); - } - - *addr = state.ipaddr; - return 0; -} - -void socketpool_resolve_host_raise(socketpool_socketpool_obj_t *self, const char *host, ip_addr_t *addr) { - int result = socketpool_resolve_host(self, host, addr); - if (result < 0) { - printf("socket_resolve_host() returned %d\n", result); - common_hal_socketpool_socketpool_raise_gaierror_noname(); - mp_raise_OSError(-result); - } -} - mp_obj_t common_hal_socketpool_socketpool_gethostbyname(socketpool_socketpool_obj_t *self, const char *host) { ip_addr_t addr; - socketpool_resolve_host_raise(self, host, &addr); + socketpool_resolve_host_raise(host, &addr); char ip_str[IP4ADDR_STRLEN_MAX]; inet_ntoa_r(addr, ip_str, IP4ADDR_STRLEN_MAX); diff --git a/ports/raspberrypi/common-hal/socketpool/SocketPool.h b/ports/raspberrypi/common-hal/socketpool/SocketPool.h index 1c60d5109635..864a52b32830 100644 --- a/ports/raspberrypi/common-hal/socketpool/SocketPool.h +++ b/ports/raspberrypi/common-hal/socketpool/SocketPool.h @@ -13,5 +13,3 @@ typedef struct { mp_obj_base_t base; } socketpool_socketpool_obj_t; - -void socketpool_resolve_host_raise(socketpool_socketpool_obj_t *self, const char *host, ip_addr_t *addr); diff --git a/ports/raspberrypi/common-hal/socketpool/__init__.c b/ports/raspberrypi/common-hal/socketpool/__init__.c index c8558f9b80a3..84a5309ae112 100644 --- a/ports/raspberrypi/common-hal/socketpool/__init__.c +++ b/ports/raspberrypi/common-hal/socketpool/__init__.c @@ -4,10 +4,78 @@ // // SPDX-License-Identifier: MIT +#include "py/runtime.h" +#include "shared/runtime/interrupt_char.h" + #include "shared-bindings/socketpool/__init__.h" +#include "shared-bindings/socketpool/SocketPool.h" +#include "shared-bindings/wifi/__init__.h" +#include "common-hal/socketpool/__init__.h" + +#include "lwip/dns.h" +#include "lwip/inet.h" -#include "common-hal/socketpool/Socket.h" void socketpool_user_reset(void) { socket_user_reset(); } + +typedef struct _getaddrinfo_state_t { + volatile int status; + volatile ip_addr_t ipaddr; +} getaddrinfo_state_t; + +static void lwip_getaddrinfo_cb(const char *name, const ip_addr_t *ipaddr, void *arg) { + getaddrinfo_state_t *state = arg; + if (ipaddr != NULL) { + state->status = 1; + state->ipaddr = *ipaddr; + } else { + // error + state->status = -2; + } +} + + +static int socketpool_resolve_host(const char *host, ip_addr_t *addr) { + + getaddrinfo_state_t state; + state.status = 0; + + MICROPY_PY_LWIP_ENTER + err_t ret = dns_gethostbyname(host, (ip_addr_t *)&state.ipaddr, lwip_getaddrinfo_cb, &state); + MICROPY_PY_LWIP_EXIT + + switch (ret) { + case ERR_OK: + // cached + state.status = 1; + break; + case ERR_INPROGRESS: + while (state.status == 0) { + RUN_BACKGROUND_TASKS; + if (mp_hal_is_interrupted()) { + break; + } + } + break; + default: + state.status = ret; + } + + if (state.status < 0) { + return state.status; + } + + *addr = state.ipaddr; + return 0; +} + +void socketpool_resolve_host_raise(const char *host, ip_addr_t *addr) { + int result = socketpool_resolve_host(host, addr); + if (result < 0) { + printf("socket_resolve_host() returned %d\n", result); + common_hal_socketpool_socketpool_raise_gaierror_noname(); + mp_raise_OSError(-result); + } +} diff --git a/ports/raspberrypi/common-hal/socketpool/__init__.h b/ports/raspberrypi/common-hal/socketpool/__init__.h index f7ccde7f3678..d55e720b373b 100644 --- a/ports/raspberrypi/common-hal/socketpool/__init__.h +++ b/ports/raspberrypi/common-hal/socketpool/__init__.h @@ -5,3 +5,8 @@ // SPDX-License-Identifier: MIT #pragma once + +#include "lwip/ip_addr.h" + +mp_obj_t socketpool_ip_addr_to_str(const ip_addr_t *addr); +void socketpool_resolve_host_raise(const char *host, ip_addr_t *addr); diff --git a/ports/raspberrypi/common-hal/wifi/Radio.c b/ports/raspberrypi/common-hal/wifi/Radio.c index 41eec00357db..5a7d2170342f 100644 --- a/ports/raspberrypi/common-hal/wifi/Radio.c +++ b/ports/raspberrypi/common-hal/wifi/Radio.c @@ -21,6 +21,7 @@ #include "shared-bindings/wifi/AuthMode.h" #include "shared-bindings/time/__init__.h" #include "shared-module/ipaddress/__init__.h" +#include "common-hal/socketpool/__init__.h" #include "lwip/sys.h" #include "lwip/dns.h" @@ -522,3 +523,40 @@ void common_hal_wifi_radio_gc_collect(wifi_radio_obj_t *self) { // Only bother to scan the actual object references. gc_collect_ptr(self->current_scan); } + +mp_obj_t common_hal_wifi_radio_get_addresses(wifi_radio_obj_t *self) { + if (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) != CYW43_LINK_UP) { + return mp_const_empty_tuple; + } + mp_obj_t args[] = { + socketpool_ip_addr_to_str(&NETIF_STA->ip_addr), + }; + return mp_obj_new_tuple(1, args); +} + +mp_obj_t common_hal_wifi_radio_get_addresses_ap(wifi_radio_obj_t *self) { + if (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_AP) != CYW43_LINK_UP) { + return mp_const_empty_tuple; + } + mp_obj_t args[] = { + socketpool_ip_addr_to_str(&NETIF_AP->ip_addr), + }; + return mp_obj_new_tuple(MP_ARRAY_SIZE(args), args); +} + +mp_obj_t common_hal_wifi_radio_get_dns(wifi_radio_obj_t *self) { + const ip_addr_t *dns_addr = dns_getserver(0); + if (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) != CYW43_LINK_UP || dns_addr->addr == 0) { + return mp_const_empty_tuple; + } + mp_obj_t args[] = { + socketpool_ip_addr_to_str(dns_addr), + }; + return mp_obj_new_tuple(MP_ARRAY_SIZE(args), args); +} + +void common_hal_wifi_radio_set_dns(wifi_radio_obj_t *self, mp_obj_t dns_addr) { + ip_addr_t addr; + socketpool_resolve_host_raise(dns_addr, &addr); + dns_setserver(0, &addr); +} From 06936448fa76d581a22f882d1a7ce6659f95be51 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 19 Jul 2024 12:39:33 -0500 Subject: [PATCH 10/18] enable v6 across all espressif boards --- ports/espressif/boards/adafruit_metro_esp32s2/sdkconfig | 4 ---- ports/espressif/esp-idf-config/sdkconfig.defaults | 6 ++++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ports/espressif/boards/adafruit_metro_esp32s2/sdkconfig b/ports/espressif/boards/adafruit_metro_esp32s2/sdkconfig index 3258b81da529..e69de29bb2d1 100644 --- a/ports/espressif/boards/adafruit_metro_esp32s2/sdkconfig +++ b/ports/espressif/boards/adafruit_metro_esp32s2/sdkconfig @@ -1,4 +0,0 @@ - -CONFIG_LWIP_IPV6_AUTOCONFIG=y -CONFIG_LWIP_IPV6_RDNSS_MAX_DNS_SERVERS=2 -CONFIG_LWIP_IPV6_DHCP6=y diff --git a/ports/espressif/esp-idf-config/sdkconfig.defaults b/ports/espressif/esp-idf-config/sdkconfig.defaults index 3bf498bc6930..c11591b3cf92 100644 --- a/ports/espressif/esp-idf-config/sdkconfig.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig.defaults @@ -64,6 +64,12 @@ CONFIG_FREERTOS_HZ=1000 CONFIG_LWIP_MAX_SOCKETS=8 CONFIG_LWIP_SO_RCVBUF=y # +# IPv6 +# +CONFIG_LWIP_IPV6_AUTOCONFIG=y +CONFIG_LWIP_IPV6_RDNSS_MAX_DNS_SERVERS=2 +CONFIG_LWIP_IPV6_DHCP6=y +# # TCP # CONFIG_LWIP_MAX_ACTIVE_TCP=4 From 85153da161108bcf211aa09ccf3fb53ed0902153 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 22 Jul 2024 09:29:28 -0500 Subject: [PATCH 11/18] Disable v6 on a couple of espressif boards where it doesn't fit --- ports/espressif/boards/lolin_c3_pico/mpconfigboard.mk | 3 +++ .../espressif/boards/waveshare_esp32_s3_tiny/mpconfigboard.mk | 3 +++ 2 files changed, 6 insertions(+) diff --git a/ports/espressif/boards/lolin_c3_pico/mpconfigboard.mk b/ports/espressif/boards/lolin_c3_pico/mpconfigboard.mk index 51b1adfe5a1d..25027d4c97b8 100644 --- a/ports/espressif/boards/lolin_c3_pico/mpconfigboard.mk +++ b/ports/espressif/boards/lolin_c3_pico/mpconfigboard.mk @@ -11,5 +11,8 @@ CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 +# Not enough flash +CIRCUITPY_SOCKETPOOL_IPV6 = 0 + # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/espressif/boards/waveshare_esp32_s3_tiny/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_tiny/mpconfigboard.mk index 334e3159c87c..836ab1b903bd 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_tiny/mpconfigboard.mk +++ b/ports/espressif/boards/waveshare_esp32_s3_tiny/mpconfigboard.mk @@ -12,3 +12,6 @@ CIRCUITPY_ESP_FLASH_SIZE = 4MB CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m + +# Not enough flash +CIRCUITPY_SOCKETPOOL_IPV6 = 0 From bc2e6b48fd3538857009a1177aa914c25f009428 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 22 Jul 2024 09:48:50 -0500 Subject: [PATCH 12/18] Finish turning dns into a tuple to accomodate multiple servers some day --- ports/espressif/common-hal/wifi/Radio.c | 29 ++++++++++++++++++----- ports/raspberrypi/common-hal/wifi/Radio.c | 11 +++++++-- shared-bindings/wifi/Radio.c | 2 +- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/ports/espressif/common-hal/wifi/Radio.c b/ports/espressif/common-hal/wifi/Radio.c index cdea302b6e19..8a6448dc99d1 100644 --- a/ports/espressif/common-hal/wifi/Radio.c +++ b/ports/espressif/common-hal/wifi/Radio.c @@ -642,18 +642,35 @@ void common_hal_wifi_radio_gc_collect(wifi_radio_obj_t *self) { mp_obj_t common_hal_wifi_radio_get_dns(wifi_radio_obj_t *self) { if (!esp_netif_is_netif_up(self->netif)) { - return mp_const_none; + return mp_const_empty_tuple; } esp_netif_get_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &self->dns_info); - return espaddr_to_str(&self->dns_info.ip); + if (self->dns_info.ip.type == ESP_IPADDR_TYPE_V4 && self->dns_info.ip.u_addr.ip4.addr == INADDR_NONE) { + return mp_const_empty_tuple; + } + + mp_obj_t args[] = { + espaddr_to_str(&self->dns_info.ip), + }; + + return mp_obj_new_tuple(1, args); } -void common_hal_wifi_radio_set_dns(wifi_radio_obj_t *self, mp_obj_t dns_addr_obj) { - struct sockaddr_storage addr_storage; - socketpool_resolve_host_or_throw(AF_UNSPEC, SOCK_STREAM, mp_obj_str_get_str(dns_addr_obj), &addr_storage, 1); +void common_hal_wifi_radio_set_dns(wifi_radio_obj_t *self, mp_obj_t dns_addrs_obj) { + mp_int_t len = mp_obj_get_int(mp_obj_len(dns_addrs_obj)); + mp_arg_validate_length_max(len, 1, MP_QSTR_dns); esp_netif_dns_info_t dns_info; - sockaddr_to_espaddr(&addr_storage, &dns_info.ip); + if (len == 0) { + // clear DNS server + dns_info.ip.type = ESP_IPADDR_TYPE_V4; + dns_info.ip.u_addr.ip4.addr = INADDR_NONE; + } else { + mp_obj_t dns_addr_obj = mp_obj_subscr(dns_addrs_obj, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL); + struct sockaddr_storage addr_storage; + socketpool_resolve_host_or_throw(AF_UNSPEC, SOCK_STREAM, mp_obj_str_get_str(dns_addr_obj), &addr_storage, 1); + sockaddr_to_espaddr(&addr_storage, &dns_info.ip); + } esp_netif_set_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &dns_info); } diff --git a/ports/raspberrypi/common-hal/wifi/Radio.c b/ports/raspberrypi/common-hal/wifi/Radio.c index 5a7d2170342f..d694b87eb9d9 100644 --- a/ports/raspberrypi/common-hal/wifi/Radio.c +++ b/ports/raspberrypi/common-hal/wifi/Radio.c @@ -555,8 +555,15 @@ mp_obj_t common_hal_wifi_radio_get_dns(wifi_radio_obj_t *self) { return mp_obj_new_tuple(MP_ARRAY_SIZE(args), args); } -void common_hal_wifi_radio_set_dns(wifi_radio_obj_t *self, mp_obj_t dns_addr) { +void common_hal_wifi_radio_set_dns(wifi_radio_obj_t *self, mp_obj_t dns_addrs_obj) { + mp_int_t len = mp_obj_get_int(mp_obj_len(dns_addrs_obj)); + mp_arg_validate_length_max(len, 1, MP_QSTR_dns); ip_addr_t addr; - socketpool_resolve_host_raise(dns_addr, &addr); + if (len == 0) { + addr.addr = IPADDR_NONE; + } else { + mp_obj_t dns_addr_obj = mp_obj_subscr(dns_addrs_obj, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL); + socketpool_resolve_host_raise(dns_addr_obj, &addr); + } dns_setserver(0, &addr); } diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c index f68ad8315bfa..465d82a199cc 100644 --- a/shared-bindings/wifi/Radio.c +++ b/shared-bindings/wifi/Radio.c @@ -661,7 +661,7 @@ MP_PROPERTY_GETSET(wifi_radio_ipv4_dns_obj, (mp_obj_t)&wifi_radio_get_ipv4_dns_obj, (mp_obj_t)&wifi_radio_set_ipv4_dns_obj); -//| dns: str +//| dns: Sequence[str] //| """Address of the DNS server to be used.""" static mp_obj_t wifi_radio_get_dns(mp_obj_t self) { return common_hal_wifi_radio_get_dns(self); From 5ffc4b2f4f8bee0a95e5b00c240a89fa60e75aa3 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 22 Jul 2024 10:48:47 -0500 Subject: [PATCH 13/18] Tick more boxes on the TODO list * v6 on by default * dhcp can start v4 & v6 separately * self documenting property for v4 & v6 support * v4 support is always on .. for now --- docs/shared_bindings_matrix.py | 1 + ports/espressif/common-hal/wifi/Radio.c | 16 +++++++++--- ports/espressif/common-hal/wifi/__init__.c | 4 +++ ports/raspberrypi/common-hal/wifi/Radio.c | 8 ++++-- shared-bindings/wifi/Radio.c | 23 +++++++++++++---- shared-bindings/wifi/Radio.h | 2 +- shared-bindings/wifi/__init__.c | 29 +++++++++++++++++++++- 7 files changed, 70 insertions(+), 13 deletions(-) diff --git a/docs/shared_bindings_matrix.py b/docs/shared_bindings_matrix.py index 0f98a5e16755..d61b2536f7ed 100644 --- a/docs/shared_bindings_matrix.py +++ b/docs/shared_bindings_matrix.py @@ -85,6 +85,7 @@ "sys": "CIRCUITPY_SYS", "terminalio": "CIRCUITPY_DISPLAYIO", "usb": "CIRCUITPY_PYUSB", + "wifi.supports_ipv6": "CIRCUITPY_SOCKETPOOL_IPV6", } MODULES_NOT_IN_BINDINGS = ["binascii", "errno", "json", "re", "ulab"] diff --git a/ports/espressif/common-hal/wifi/Radio.c b/ports/espressif/common-hal/wifi/Radio.c index 8a6448dc99d1..c09d0cf59cb0 100644 --- a/ports/espressif/common-hal/wifi/Radio.c +++ b/ports/espressif/common-hal/wifi/Radio.c @@ -532,11 +532,19 @@ void common_hal_wifi_radio_set_ipv4_dns(wifi_radio_obj_t *self, mp_obj_t ipv4_dn esp_netif_set_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &dns_addr); } -void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self) { - esp_netif_dhcpc_start(self->netif); +void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self, bool ipv4, bool ipv6) { + if (ipv4) { + esp_netif_dhcpc_start(self->netif); + } else { + esp_netif_dhcpc_stop(self->netif); + } #if LWIP_IPV6_DHCP6 - esp_netif_create_ip6_linklocal(self->netif); - dhcp6_enable_stateless(esp_netif_get_netif_impl(self->netif)); + if (ipv6) { + esp_netif_create_ip6_linklocal(self->netif); + dhcp6_enable_stateless(esp_netif_get_netif_impl(self->netif)); + } else { + dhcp6_disable(esp_netif_get_netif_impl(self->netif)); + } #endif } diff --git a/ports/espressif/common-hal/wifi/__init__.c b/ports/espressif/common-hal/wifi/__init__.c index b005d8993e78..ce84c4b2619a 100644 --- a/ports/espressif/common-hal/wifi/__init__.c +++ b/ports/espressif/common-hal/wifi/__init__.c @@ -136,6 +136,8 @@ void common_hal_wifi_init(bool user_initiated) { if (wifi_inited) { if (user_initiated && !wifi_user_initiated) { common_hal_wifi_radio_set_enabled(self, true); + // explicitly start dhcp + common_hal_wifi_radio_start_dhcp_client(self, true, true); } return; } @@ -201,6 +203,8 @@ void common_hal_wifi_init(bool user_initiated) { common_hal_wifi_radio_start_station(self); // start wifi common_hal_wifi_radio_set_enabled(self, true); + // explicitly start dhcp + common_hal_wifi_radio_start_dhcp_client(self, true, true); } void wifi_user_reset(void) { diff --git a/ports/raspberrypi/common-hal/wifi/Radio.c b/ports/raspberrypi/common-hal/wifi/Radio.c index d694b87eb9d9..2369c35f69b2 100644 --- a/ports/raspberrypi/common-hal/wifi/Radio.c +++ b/ports/raspberrypi/common-hal/wifi/Radio.c @@ -406,8 +406,12 @@ void common_hal_wifi_radio_set_ipv4_dns(wifi_radio_obj_t *self, mp_obj_t ipv4_dn dns_setserver(0, &addr); } -void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self) { - dhcp_start(NETIF_STA); +void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self, bool ipv4, bool ipv6) { + if (ipv4) { + dhcp_start(NETIF_STA); + } else { + dhcp_stop(NETIF_STA); + } } void common_hal_wifi_radio_stop_dhcp_client(wifi_radio_obj_t *self) { diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c index 465d82a199cc..79d1bb4cf5bf 100644 --- a/shared-bindings/wifi/Radio.c +++ b/shared-bindings/wifi/Radio.c @@ -700,14 +700,27 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_stations_ap_obj, wifi_radio_get_station MP_PROPERTY_GETTER(wifi_radio_stations_ap_obj, (mp_obj_t)&wifi_radio_get_stations_ap_obj); -//| def start_dhcp(self) -> None: -//| """Starts the station DHCP client.""" +//| def start_dhcp(self, *, ipv4: bool = supports_ipv4, ipv6: bool = supports_ipv6) -> None: +//| """Starts the station DHCP client. +//| +//| If specified +//| """ //| ... -static mp_obj_t wifi_radio_start_dhcp_client(mp_obj_t self) { - common_hal_wifi_radio_start_dhcp_client(self); +static mp_obj_t wifi_radio_start_dhcp_client(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_ipv4, ARG_ipv6 }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_ipv4, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = MP_ROM_TRUE } }, + { MP_QSTR_ipv6, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = CIRCUITPY_SOCKETPOOL_IPV6 ? MP_ROM_TRUE : MP_ROM_FALSE } }, + }; + + wifi_radio_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + common_hal_wifi_radio_start_dhcp_client(self, args[ARG_ipv4].u_bool, args[ARG_ipv6].u_bool); return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_start_dhcp_client_obj, wifi_radio_start_dhcp_client); +static MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_start_dhcp_client_obj, 1, wifi_radio_start_dhcp_client); //| def stop_dhcp(self) -> None: //| """Stops the station DHCP client. Needed to assign a static IP address.""" diff --git a/shared-bindings/wifi/Radio.h b/shared-bindings/wifi/Radio.h index e8527c3f8a09..8a5391a8ccbe 100644 --- a/shared-bindings/wifi/Radio.h +++ b/shared-bindings/wifi/Radio.h @@ -86,7 +86,7 @@ extern void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self); extern bool common_hal_wifi_radio_get_ap_active(wifi_radio_obj_t *self); extern mp_obj_t common_hal_wifi_radio_get_stations_ap(wifi_radio_obj_t *self); -extern void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self); +extern void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self, bool ipv4, bool ipv6); extern void common_hal_wifi_radio_stop_dhcp_client(wifi_radio_obj_t *self); extern void common_hal_wifi_radio_start_dhcp_server(wifi_radio_obj_t *self); extern void common_hal_wifi_radio_stop_dhcp_server(wifi_radio_obj_t *self); diff --git a/shared-bindings/wifi/__init__.c b/shared-bindings/wifi/__init__.c index 988b07147c2d..dd95fb4fec4d 100644 --- a/shared-bindings/wifi/__init__.c +++ b/shared-bindings/wifi/__init__.c @@ -13,8 +13,32 @@ //| """ //| The `wifi` module provides necessary low-level functionality for managing -//| wifi connections. Use `socketpool` for communicating over the network.""" +//| wifi connections. Use `socketpool` for communicating over the network. //| +//| .. jinja +//| """ + +//| supports_ipv6: bool +//| """``True`` when ipv6 is supported. Read-only +//| +//| .. raw:: html +//| +//|

+//|

+//| True on these boards +//|
    +//| {% for board in support_matrix_reverse["wifi.supports_ipv6"] %} +//|
  • {{ board }} +//| {% endfor %} +//|
+//|
+//|

+//| +//| """ + +//| supports_ipv4: bool +//| """``True`` when ipv4 is supported. Read-only""" + //| radio: Radio //| """Wifi radio used to manage both station and AP modes. //| This object is the sole instance of `wifi.Radio`.""" @@ -43,6 +67,9 @@ static const mp_rom_map_elem_t wifi_module_globals_table[] = { // Properties { MP_ROM_QSTR(MP_QSTR_radio), MP_ROM_PTR(&common_hal_wifi_radio_obj) }, + + { MP_ROM_QSTR(MP_QSTR_supports_ipv6), MP_ROM_PTR(CIRCUITPY_SOCKETPOOL_IPV6 ? MP_ROM_TRUE : MP_ROM_FALSE) }, + { MP_ROM_QSTR(MP_QSTR_supports_ipv4), MP_ROM_TRUE }, }; static MP_DEFINE_CONST_DICT(wifi_module_globals, wifi_module_globals_table); From 841850e1b8a707736505bc197695c4db17696db9 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 22 Jul 2024 10:58:29 -0500 Subject: [PATCH 14/18] raspberrypi: implement ping of string address --- ports/raspberrypi/common-hal/wifi/Radio.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ports/raspberrypi/common-hal/wifi/Radio.c b/ports/raspberrypi/common-hal/wifi/Radio.c index 2369c35f69b2..18470af73b42 100644 --- a/ports/raspberrypi/common-hal/wifi/Radio.c +++ b/ports/raspberrypi/common-hal/wifi/Radio.c @@ -486,7 +486,11 @@ ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) mp_int_t common_hal_wifi_radio_ping(wifi_radio_obj_t *self, mp_obj_t ip_address, mp_float_t timeout) { ping_time = sys_now(); ip_addr_t ping_addr; - ipaddress_ipaddress_to_lwip(ip_address, &ping_addr); + if (mp_obj_is_str(ip_address)) { + socketpool_resolve_host_raise(mp_obj_str_get_str(ip_address), &ping_addr); + } else { + ipaddress_ipaddress_to_lwip(ip_address, &ping_addr); + } struct raw_pcb *ping_pcb; MICROPY_PY_LWIP_ENTER From 34bee5992088e68eeec83a81262996c3f1b07372 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 22 Jul 2024 12:46:56 -0500 Subject: [PATCH 15/18] espressif: actually disable v6 support on select boards --- .../espressif/boards/lolin_c3_pico/sdkconfig | 1 + .../boards/waveshare_esp32_s3_tiny/sdkconfig | 1 + .../espressif/common-hal/socketpool/Socket.c | 8 ++++--- ports/espressif/common-hal/wifi/Radio.c | 8 ++++++- ports/espressif/common-hal/wifi/__init__.c | 22 +++++++++++++++---- shared-bindings/wifi/Radio.c | 7 ------ 6 files changed, 32 insertions(+), 15 deletions(-) diff --git a/ports/espressif/boards/lolin_c3_pico/sdkconfig b/ports/espressif/boards/lolin_c3_pico/sdkconfig index 00134fd0f29e..ba2885933e79 100644 --- a/ports/espressif/boards/lolin_c3_pico/sdkconfig +++ b/ports/espressif/boards/lolin_c3_pico/sdkconfig @@ -7,6 +7,7 @@ # # LWIP # +# CONFIG_LWIP_IPV6 is not set CONFIG_LWIP_LOCAL_HOSTNAME="lolin-c3-pico" # end of LWIP diff --git a/ports/espressif/boards/waveshare_esp32_s3_tiny/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_tiny/sdkconfig index a491b9f5f019..19f833ad74ce 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_tiny/sdkconfig +++ b/ports/espressif/boards/waveshare_esp32_s3_tiny/sdkconfig @@ -7,6 +7,7 @@ # # LWIP # +# CONFIG_LWIP_IPV6 is not set CONFIG_LWIP_LOCAL_HOSTNAME="waveshare-esp32-s3-tiny" # end of LWIP diff --git a/ports/espressif/common-hal/socketpool/Socket.c b/ports/espressif/common-hal/socketpool/Socket.c index 14649e63c909..9fc04728a4d4 100644 --- a/ports/espressif/common-hal/socketpool/Socket.c +++ b/ports/espressif/common-hal/socketpool/Socket.c @@ -195,7 +195,7 @@ static bool _socketpool_socket(socketpool_socketpool_obj_t *self, if (family == SOCKETPOOL_AF_INET) { addr_family = AF_INET; ipproto = IPPROTO_IP; - #if LWIP_IPV6 + #if CIRCUITPY_SOCKETPOOL_IPV6 } else { // INET6 addr_family = AF_INET6; ipproto = IPPROTO_IPV6; @@ -345,7 +345,6 @@ socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_o } } -// TODO: ipv6 size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self, const char *host, size_t hostlen, uint32_t port) { struct sockaddr_storage bind_addr; @@ -353,6 +352,7 @@ size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self, bind_addr.ss_family = self->family; + #if CIRCUITPY_SOCKETPOOL_IPV6 if (self->family == AF_INET6) { struct sockaddr_in6 *addr6 = (void *)&bind_addr; addr6->sin6_port = htons(port); @@ -362,7 +362,9 @@ size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self, } else { socketpool_resolve_host_or_throw(self->family, self->type, host, &bind_addr, port); } - } else { + } else + #endif + { struct sockaddr_in *addr4 = (void *)&bind_addr; addr4->sin_port = htons(port); if (hostlen == 0) { diff --git a/ports/espressif/common-hal/wifi/Radio.c b/ports/espressif/common-hal/wifi/Radio.c index c09d0cf59cb0..7fdffb895012 100644 --- a/ports/espressif/common-hal/wifi/Radio.c +++ b/ports/espressif/common-hal/wifi/Radio.c @@ -461,14 +461,20 @@ static mp_obj_t common_hal_wifi_radio_get_addresses_netif(wifi_radio_obj_t *self esp_netif_get_ip_info(netif, &ip_info); int n_addresses4 = ip_info.ip.addr != INADDR_NONE; + #if CIRCUITPY_SOCKETPOOL_IPV6 esp_ip6_addr_t addresses[LWIP_IPV6_NUM_ADDRESSES]; int n_addresses6 = esp_netif_get_all_ip6(netif, &addresses[0]); + #else + int n_addresses6 = 0; + #endif int n_addresses = n_addresses4 + n_addresses6; - mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_addresses, NULL)); + + #if CIRCUITPY_SOCKETPOOL_IPV6 for (int i = 0; i < n_addresses6; i++) { result->items[i] = espaddr6_to_str(&addresses[i]); } + #endif if (n_addresses4) { result->items[n_addresses6] = espaddr4_to_str(&ip_info.ip); diff --git a/ports/espressif/common-hal/wifi/__init__.c b/ports/espressif/common-hal/wifi/__init__.c index ce84c4b2619a..22c34a0f58f2 100644 --- a/ports/espressif/common-hal/wifi/__init__.c +++ b/ports/espressif/common-hal/wifi/__init__.c @@ -241,7 +241,9 @@ void wifi_reset(void) { void ipaddress_ipaddress_to_esp_idf(mp_obj_t ip_address, ip_addr_t *esp_ip_address) { if (mp_obj_is_type(ip_address, &ipaddress_ipv4address_type)) { ipaddress_ipaddress_to_esp_idf_ip4(ip_address, (esp_ip4_addr_t *)esp_ip_address); + #if LWIP_IPV6 esp_ip_address->type = IPADDR_TYPE_V4; + #endif } else { struct sockaddr_storage addr_storage; socketpool_resolve_host_or_throw(AF_UNSPEC, SOCK_STREAM, mp_obj_str_get_str(ip_address), &addr_storage, 1); @@ -283,10 +285,13 @@ mp_obj_t espaddr6_to_str(const esp_ip6_addr_t *espaddr) { mp_obj_t sockaddr_to_str(const struct sockaddr_storage *sockaddr) { char buf[IPADDR_STRLEN_MAX]; + #if CIRCUITPY_SOCKETPOOL_IPV6 if (sockaddr->ss_family == AF_INET6) { const struct sockaddr_in6 *addr6 = (const void *)sockaddr; inet_ntop(AF_INET6, &addr6->sin6_addr, buf, sizeof(buf)); - } else { + } else + #endif + { const struct sockaddr_in *addr = (const void *)sockaddr; inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)); } @@ -298,13 +303,16 @@ mp_obj_t sockaddr_to_tuple(const struct sockaddr_storage *sockaddr) { sockaddr_to_str(sockaddr), }; int n = 2; + #if CIRCUITPY_SOCKETPOOL_IPV6 if (sockaddr->ss_family == AF_INET6) { const struct sockaddr_in6 *addr6 = (const void *)sockaddr; args[1] = MP_OBJ_NEW_SMALL_INT(htons(addr6->sin6_port)); args[2] = MP_OBJ_NEW_SMALL_INT(addr6->sin6_flowinfo); args[3] = MP_OBJ_NEW_SMALL_INT(addr6->sin6_scope_id); n = 4; - } else { + } else + #endif + { const struct sockaddr_in *addr = (const void *)sockaddr; args[1] = MP_OBJ_NEW_SMALL_INT(htons(addr->sin_port)); } @@ -312,6 +320,7 @@ mp_obj_t sockaddr_to_tuple(const struct sockaddr_storage *sockaddr) { } void sockaddr_to_espaddr(const struct sockaddr_storage *sockaddr, esp_ip_addr_t *espaddr) { + #if CIRCUITPY_SOCKETPOOL_IPV6 MP_STATIC_ASSERT(IPADDR_TYPE_V4 == ESP_IPADDR_TYPE_V4); MP_STATIC_ASSERT(IPADDR_TYPE_V6 == ESP_IPADDR_TYPE_V6); MP_STATIC_ASSERT(sizeof(ip_addr_t) == sizeof(esp_ip_addr_t)); @@ -323,7 +332,9 @@ void sockaddr_to_espaddr(const struct sockaddr_storage *sockaddr, esp_ip_addr_t memcpy(&espaddr->u_addr.ip6.addr, &addr6->sin6_addr, sizeof(espaddr->u_addr.ip6.addr)); espaddr->u_addr.ip6.zone = addr6->sin6_scope_id; espaddr->type = ESP_IPADDR_TYPE_V6; - } else { + } else + #endif + { const struct sockaddr_in *addr = (const void *)sockaddr; MP_STATIC_ASSERT(sizeof(espaddr->u_addr.ip4.addr) == sizeof(addr->sin_addr)); memcpy(&espaddr->u_addr.ip4.addr, &addr->sin_addr, sizeof(espaddr->u_addr.ip4.addr)); @@ -332,11 +343,14 @@ void sockaddr_to_espaddr(const struct sockaddr_storage *sockaddr, esp_ip_addr_t } void espaddr_to_sockaddr(const esp_ip_addr_t *espaddr, struct sockaddr_storage *sockaddr, int port) { + #if CIRCUITPY_SOCKETPOOL_IPV6 if (espaddr->type == ESP_IPADDR_TYPE_V6) { struct sockaddr_in6 *addr6 = (void *)sockaddr; memcpy(&addr6->sin6_addr, &espaddr->u_addr.ip6.addr, sizeof(espaddr->u_addr.ip6.addr)); addr6->sin6_scope_id = espaddr->u_addr.ip6.zone; - } else { + } else + #endif + { struct sockaddr_in *addr = (void *)sockaddr; memcpy(&addr->sin_addr, &espaddr->u_addr.ip4.addr, sizeof(espaddr->u_addr.ip4.addr)); } diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c index 79d1bb4cf5bf..b62bc4b74326 100644 --- a/shared-bindings/wifi/Radio.c +++ b/shared-bindings/wifi/Radio.c @@ -616,13 +616,6 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_addresses_ap_obj, _wifi_radio_get_addre MP_PROPERTY_GETTER(wifi_radio_addresses_ap_obj, (mp_obj_t)&wifi_radio_get_addresses_ap_obj); - -#if 0 -MP_WEAK mp_obj_t common_hal_wifi_radio_get_addresses(wifi_radio_obj_t *self) { - return mp_const_none; -} -#endif - //| ipv4_address: Optional[ipaddress.IPv4Address] //| """IP v4 Address of the station when connected to an access point. None otherwise. (read-only)""" static mp_obj_t _wifi_radio_get_ipv4_address(mp_obj_t self) { From 99e5e665182003d9926d5dc532245a42d8a05b3e Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 22 Jul 2024 16:20:34 -0500 Subject: [PATCH 16/18] socketpool: Always use getaddrinfo_raise. --- .../common-hal/socketpool/SocketPool.c | 36 +++++-------------- .../common-hal/socketpool/SocketPool.c | 24 +++++++++++-- shared-bindings/socketpool/SocketPool.c | 34 ------------------ shared-bindings/socketpool/SocketPool.h | 8 ----- 4 files changed, 29 insertions(+), 73 deletions(-) diff --git a/ports/espressif/common-hal/socketpool/SocketPool.c b/ports/espressif/common-hal/socketpool/SocketPool.c index 190724e0f76c..aa7461d3ffe8 100644 --- a/ports/espressif/common-hal/socketpool/SocketPool.c +++ b/ports/espressif/common-hal/socketpool/SocketPool.c @@ -60,48 +60,30 @@ static mp_obj_t format_address(const struct sockaddr *addr, int family) { return mp_obj_new_str(ip_str, strlen(ip_str)); } -mp_obj_t common_hal_socketpool_socketpool_gethostbyname(socketpool_socketpool_obj_t *self, - const char *host) { - - const struct addrinfo hints = { - .ai_family = AF_INET, - .ai_socktype = SOCK_STREAM, - }; - struct addrinfo *res = NULL; - int err = socketpool_getaddrinfo_common(host, 0, &hints, &res); - if (err != 0 || res == NULL) { - return mp_const_none; - } - - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - mp_obj_t result = format_address(res->ai_addr, res->ai_family); - nlr_pop(); - lwip_freeaddrinfo(res); - return result; - } else { - lwip_freeaddrinfo(res); - nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val)); - }; -} - -#if CIRCUITPY_SOCKETPOOL_IPV6 static mp_obj_t convert_sockaddr(const struct addrinfo *ai, int port) { + #if CIRCUITPY_SOCKETPOOL_IPV6 mp_int_t n_tuple = ai->ai_family == AF_INET6 ? 4 : 2; + #else + mp_int_t n_tuple = 2; + #endif mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_tuple, NULL)); result->items[0] = format_address(ai->ai_addr, ai->ai_family); result->items[1] = MP_OBJ_NEW_SMALL_INT(port); + #if CIRCUITPY_SOCKETPOOL_IPV6 if (ai->ai_family == AF_INET6) { const struct sockaddr_in6 *ai6 = (void *)ai->ai_addr; result->items[2] = MP_OBJ_NEW_SMALL_INT(ai6->sin6_flowinfo); result->items[3] = MP_OBJ_NEW_SMALL_INT(ai6->sin6_scope_id); } + #endif return result; } static mp_obj_t convert_addrinfo(const struct addrinfo *ai, int port) { MP_STATIC_ASSERT(AF_INET == SOCKETPOOL_AF_INET); + #if CIRCUITPY_SOCKETPOOL_IPV6 MP_STATIC_ASSERT(AF_INET6 == SOCKETPOOL_AF_INET6); + #endif // MP_STATIC_ASSERT(AF_UNSPEC == SOCKETPOOL_AF_UNSPEC); mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); result->items[0] = MP_OBJ_NEW_SMALL_INT(ai->ai_family); @@ -113,7 +95,6 @@ static mp_obj_t convert_addrinfo(const struct addrinfo *ai, int port) { } 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) { - MP_STATIC_ASSERT(LWIP_IPV6); const struct addrinfo hints = { .ai_flags = flags, .ai_family = family, @@ -141,4 +122,3 @@ mp_obj_t common_hal_socketpool_getaddrinfo_raise(socketpool_socketpool_obj_t *se nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val)); } } -#endif diff --git a/ports/raspberrypi/common-hal/socketpool/SocketPool.c b/ports/raspberrypi/common-hal/socketpool/SocketPool.c index 200967ca6eb2..394b97799338 100644 --- a/ports/raspberrypi/common-hal/socketpool/SocketPool.c +++ b/ports/raspberrypi/common-hal/socketpool/SocketPool.c @@ -10,6 +10,7 @@ #include "shared/runtime/interrupt_char.h" #include "py/runtime.h" #include "shared-bindings/wifi/__init__.h" +#include "shared-bindings/ipaddress/__init__.h" #include "lwip/dns.h" #include "lwip/inet.h" @@ -22,7 +23,7 @@ void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *sel // common_hal_socketpool_socket is in socketpool/Socket.c to centralize open socket tracking. -mp_obj_t common_hal_socketpool_socketpool_gethostbyname(socketpool_socketpool_obj_t *self, const char *host) { +static mp_obj_t common_hal_socketpool_socketpool_gethostbyname_raise(socketpool_socketpool_obj_t *self, const char *host) { ip_addr_t addr; socketpool_resolve_host_raise(host, &addr); @@ -33,6 +34,23 @@ mp_obj_t common_hal_socketpool_socketpool_gethostbyname(socketpool_socketpool_ob return ip_obj; } -mp_obj_t common_hal_socketpool_socketpool_gethostbyname_raise(socketpool_socketpool_obj_t *self, const char *host) { - return common_hal_socketpool_socketpool_gethostbyname(self, host); +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) { + mp_obj_t ip_str; + + if (strlen(host) > 0 && ipaddress_parse_ipv4address(host, strlen(host), NULL)) { + ip_str = mp_obj_new_str(host, strlen(host)); + } else { + ip_str = common_hal_socketpool_socketpool_gethostbyname_raise(self, host); + } + + mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); + tuple->items[0] = MP_OBJ_NEW_SMALL_INT(SOCKETPOOL_AF_INET); + tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCKETPOOL_SOCK_STREAM); + tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); + tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); + mp_obj_tuple_t *sockaddr = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); + sockaddr->items[0] = ip_str; + sockaddr->items[1] = MP_OBJ_NEW_SMALL_INT(port); + tuple->items[4] = MP_OBJ_FROM_PTR(sockaddr); + return mp_obj_new_list(1, (mp_obj_t *)&tuple); } diff --git a/shared-bindings/socketpool/SocketPool.c b/shared-bindings/socketpool/SocketPool.c index b75438403037..ada850ad17d4 100644 --- a/shared-bindings/socketpool/SocketPool.c +++ b/shared-bindings/socketpool/SocketPool.c @@ -142,7 +142,6 @@ static mp_obj_t socketpool_socketpool_getaddrinfo(size_t n_args, const mp_obj_t mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - #if CIRCUITPY_SOCKETPOOL_IPV6 return common_hal_socketpool_getaddrinfo_raise( self, mp_obj_str_get_str(args[ARG_host].u_obj), @@ -151,30 +150,6 @@ static mp_obj_t socketpool_socketpool_getaddrinfo(size_t n_args, const mp_obj_t args[ARG_type].u_int, args[ARG_proto].u_int, args[ARG_flags].u_int); - #else - const char *host = mp_obj_str_get_str(args[ARG_host].u_obj); - mp_int_t port = args[ARG_port].u_int; - mp_obj_t ip_str = mp_const_none; - - if (strlen(host) > 0 && ipaddress_parse_ipv4address(host, strlen(host), NULL)) { - ip_str = args[ARG_host].u_obj; - } - - if (ip_str == mp_const_none) { - ip_str = common_hal_socketpool_socketpool_gethostbyname_raise(self, host); - } - - mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); - tuple->items[0] = MP_OBJ_NEW_SMALL_INT(SOCKETPOOL_AF_INET); - tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCKETPOOL_SOCK_STREAM); - tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); - tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); - mp_obj_tuple_t *sockaddr = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); - sockaddr->items[0] = ip_str; - sockaddr->items[1] = MP_OBJ_NEW_SMALL_INT(port); - tuple->items[4] = MP_OBJ_FROM_PTR(sockaddr); - return mp_obj_new_list(1, (mp_obj_t *)&tuple); - #endif } static MP_DEFINE_CONST_FUN_OBJ_KW(socketpool_socketpool_getaddrinfo_obj, 1, socketpool_socketpool_getaddrinfo); @@ -218,15 +193,6 @@ MP_DEFINE_CONST_OBJ_TYPE( locals_dict, &socketpool_socketpool_locals_dict ); -MP_WEAK -mp_obj_t common_hal_socketpool_socketpool_gethostbyname_raise(socketpool_socketpool_obj_t *self, const char *host) { - mp_obj_t ip_str = common_hal_socketpool_socketpool_gethostbyname(self, host); - if (ip_str == mp_const_none) { - common_hal_socketpool_socketpool_raise_gaierror_noname(); - } - return ip_str; -} - MP_WEAK NORETURN void common_hal_socketpool_socketpool_raise_gaierror_noname(void) { vstr_t vstr; diff --git a/shared-bindings/socketpool/SocketPool.h b/shared-bindings/socketpool/SocketPool.h index 48acb05d97f2..36035ed00e11 100644 --- a/shared-bindings/socketpool/SocketPool.h +++ b/shared-bindings/socketpool/SocketPool.h @@ -19,12 +19,6 @@ void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *sel socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_t *self, socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type, int proto); -mp_obj_t common_hal_socketpool_socketpool_gethostbyname(socketpool_socketpool_obj_t *self, - const char *host); -// raises an exception instead of returning mp_const_none in the case of error -mp_obj_t common_hal_socketpool_socketpool_gethostbyname_raise(socketpool_socketpool_obj_t *self, - const char *host); - // Non-allocating version for internal use. These sockets are not registered and, therefore, not // closed automatically. bool socketpool_socket(socketpool_socketpool_obj_t *self, @@ -33,6 +27,4 @@ bool socketpool_socket(socketpool_socketpool_obj_t *self, NORETURN void common_hal_socketpool_socketpool_raise_gaierror_noname(void); -#if CIRCUITPY_SOCKETPOOL_IPV6 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); -#endif From aa82a3e7330fae4c94dfeef36b534b5a69826a10 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 22 Jul 2024 16:38:48 -0500 Subject: [PATCH 17/18] Radio.start_dhcp: finish documentation. --- shared-bindings/wifi/Radio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c index b62bc4b74326..af69b648d7e2 100644 --- a/shared-bindings/wifi/Radio.c +++ b/shared-bindings/wifi/Radio.c @@ -696,7 +696,9 @@ MP_PROPERTY_GETTER(wifi_radio_stations_ap_obj, //| def start_dhcp(self, *, ipv4: bool = supports_ipv4, ipv6: bool = supports_ipv6) -> None: //| """Starts the station DHCP client. //| -//| If specified +//| By default, calling this function starts all supported types of DHCP. +//| If the ``ipv4`` and ``ipv6`` arguments are specified as `False` then +//| the corresponding DHCP client is stopped if it was active. //| """ //| ... static mp_obj_t wifi_radio_start_dhcp_client(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { From 21a5c93ada03a5453dcbf0211b258ad8d5d113b0 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 23 Jul 2024 14:18:03 -0500 Subject: [PATCH 18/18] IPv6: improvments based on review notes * don't enable ipv6 by default due to privacy concerns * move list of board support for ipv6 to socketpool documentation * removed wifi.supports_ipvx properties * throw an exception when start_dhcp_client(ipv6=True) but not supported --- docs/shared_bindings_matrix.py | 2 +- ports/espressif/common-hal/wifi/Radio.c | 4 ++++ ports/espressif/common-hal/wifi/__init__.c | 4 ---- ports/raspberrypi/common-hal/wifi/Radio.c | 3 +++ shared-bindings/socketpool/__init__.c | 15 +++++++++++++ shared-bindings/wifi/Radio.c | 10 ++++----- shared-bindings/wifi/__init__.c | 26 ---------------------- 7 files changed, 28 insertions(+), 36 deletions(-) diff --git a/docs/shared_bindings_matrix.py b/docs/shared_bindings_matrix.py index d61b2536f7ed..33dfad01e986 100644 --- a/docs/shared_bindings_matrix.py +++ b/docs/shared_bindings_matrix.py @@ -85,7 +85,7 @@ "sys": "CIRCUITPY_SYS", "terminalio": "CIRCUITPY_DISPLAYIO", "usb": "CIRCUITPY_PYUSB", - "wifi.supports_ipv6": "CIRCUITPY_SOCKETPOOL_IPV6", + "socketpool.socketpool.AF_INET6": "CIRCUITPY_SOCKETPOOL_IPV6", } MODULES_NOT_IN_BINDINGS = ["binascii", "errno", "json", "re", "ulab"] diff --git a/ports/espressif/common-hal/wifi/Radio.c b/ports/espressif/common-hal/wifi/Radio.c index 7fdffb895012..a6f3c320b922 100644 --- a/ports/espressif/common-hal/wifi/Radio.c +++ b/ports/espressif/common-hal/wifi/Radio.c @@ -551,6 +551,10 @@ void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self, bool ipv4, } else { dhcp6_disable(esp_netif_get_netif_impl(self->netif)); } + #else + if (ipv6) { + mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_ipv6); + } #endif } diff --git a/ports/espressif/common-hal/wifi/__init__.c b/ports/espressif/common-hal/wifi/__init__.c index 22c34a0f58f2..c2a63ceede72 100644 --- a/ports/espressif/common-hal/wifi/__init__.c +++ b/ports/espressif/common-hal/wifi/__init__.c @@ -136,8 +136,6 @@ void common_hal_wifi_init(bool user_initiated) { if (wifi_inited) { if (user_initiated && !wifi_user_initiated) { common_hal_wifi_radio_set_enabled(self, true); - // explicitly start dhcp - common_hal_wifi_radio_start_dhcp_client(self, true, true); } return; } @@ -203,8 +201,6 @@ void common_hal_wifi_init(bool user_initiated) { common_hal_wifi_radio_start_station(self); // start wifi common_hal_wifi_radio_set_enabled(self, true); - // explicitly start dhcp - common_hal_wifi_radio_start_dhcp_client(self, true, true); } void wifi_user_reset(void) { diff --git a/ports/raspberrypi/common-hal/wifi/Radio.c b/ports/raspberrypi/common-hal/wifi/Radio.c index 18470af73b42..3250ed4d7c7f 100644 --- a/ports/raspberrypi/common-hal/wifi/Radio.c +++ b/ports/raspberrypi/common-hal/wifi/Radio.c @@ -412,6 +412,9 @@ void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self, bool ipv4, } else { dhcp_stop(NETIF_STA); } + if (ipv6) { + mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_ipv6); + } } void common_hal_wifi_radio_stop_dhcp_client(wifi_radio_obj_t *self) { diff --git a/shared-bindings/socketpool/__init__.c b/shared-bindings/socketpool/__init__.c index 59d55bf3f836..e3e3f035ce72 100644 --- a/shared-bindings/socketpool/__init__.c +++ b/shared-bindings/socketpool/__init__.c @@ -18,6 +18,21 @@ //| //| For more information about the `socket` module, see the CPython documentation: //| https://docs.python.org/3/library/socket.html +//| +//| .. jinja +//| +//| .. raw:: html +//| +//|

+//|

+//| AF_INET6 (IPv6) supported on these boards +//|
    +//| {% for board in support_matrix_reverse["socketpool.socketpool.AF_INET6"] %} +//|
  • {{ board }} +//| {% endfor %} +//|
+//|
+//|

//| """ static const mp_rom_map_elem_t socketpool_globals_table[] = { diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c index af69b648d7e2..f6a35e28c849 100644 --- a/shared-bindings/wifi/Radio.c +++ b/shared-bindings/wifi/Radio.c @@ -693,19 +693,19 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_stations_ap_obj, wifi_radio_get_station MP_PROPERTY_GETTER(wifi_radio_stations_ap_obj, (mp_obj_t)&wifi_radio_get_stations_ap_obj); -//| def start_dhcp(self, *, ipv4: bool = supports_ipv4, ipv6: bool = supports_ipv6) -> None: +//| def start_dhcp(self, *, ipv4: bool = True, ipv6: bool = False) -> None: //| """Starts the station DHCP client. //| -//| By default, calling this function starts all supported types of DHCP. -//| If the ``ipv4`` and ``ipv6`` arguments are specified as `False` then -//| the corresponding DHCP client is stopped if it was active. +//| By default, calling this function starts DHCP for IPv4 networks but not +//| IPv6 networks. When the the ``ipv4`` and ``ipv6`` arguments are `False` +//| then the corresponding DHCP client is stopped if it was active. //| """ //| ... static mp_obj_t wifi_radio_start_dhcp_client(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_ipv4, ARG_ipv6 }; static const mp_arg_t allowed_args[] = { { MP_QSTR_ipv4, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = MP_ROM_TRUE } }, - { MP_QSTR_ipv6, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = CIRCUITPY_SOCKETPOOL_IPV6 ? MP_ROM_TRUE : MP_ROM_FALSE } }, + { MP_QSTR_ipv6, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = MP_ROM_FALSE } }, }; wifi_radio_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); diff --git a/shared-bindings/wifi/__init__.c b/shared-bindings/wifi/__init__.c index dd95fb4fec4d..3b09255052e0 100644 --- a/shared-bindings/wifi/__init__.c +++ b/shared-bindings/wifi/__init__.c @@ -14,31 +14,8 @@ //| """ //| The `wifi` module provides necessary low-level functionality for managing //| wifi connections. Use `socketpool` for communicating over the network. -//| -//| .. jinja //| """ -//| supports_ipv6: bool -//| """``True`` when ipv6 is supported. Read-only -//| -//| .. raw:: html -//| -//|

-//|

-//| True on these boards -//|
    -//| {% for board in support_matrix_reverse["wifi.supports_ipv6"] %} -//|
  • {{ board }} -//| {% endfor %} -//|
-//|
-//|

-//| -//| """ - -//| supports_ipv4: bool -//| """``True`` when ipv4 is supported. Read-only""" - //| radio: Radio //| """Wifi radio used to manage both station and AP modes. //| This object is the sole instance of `wifi.Radio`.""" @@ -67,9 +44,6 @@ static const mp_rom_map_elem_t wifi_module_globals_table[] = { // Properties { MP_ROM_QSTR(MP_QSTR_radio), MP_ROM_PTR(&common_hal_wifi_radio_obj) }, - - { MP_ROM_QSTR(MP_QSTR_supports_ipv6), MP_ROM_PTR(CIRCUITPY_SOCKETPOOL_IPV6 ? MP_ROM_TRUE : MP_ROM_FALSE) }, - { MP_ROM_QSTR(MP_QSTR_supports_ipv4), MP_ROM_TRUE }, }; static MP_DEFINE_CONST_DICT(wifi_module_globals, wifi_module_globals_table);