Merge pull request #9436 from jepler/veesix

Add IPv6 support for Espressif
This commit is contained in:
Scott Shawcroft 2024-07-23 12:43:22 -07:00 committed by GitHub
commit bffdf3beea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 738 additions and 273 deletions

View file

@ -85,6 +85,7 @@ ADDITIONAL_MODULES = {
"sys": "CIRCUITPY_SYS",
"terminalio": "CIRCUITPY_DISPLAYIO",
"usb": "CIRCUITPY_PYUSB",
"socketpool.socketpool.AF_INET6": "CIRCUITPY_SOCKETPOOL_IPV6",
}
MODULES_NOT_IN_BINDINGS = ["binascii", "errno", "json", "re", "ulab"]

View file

@ -1562,7 +1562,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 ""
@ -2224,6 +2223,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"

View file

@ -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

View file

@ -7,6 +7,7 @@
#
# LWIP
#
# CONFIG_LWIP_IPV6 is not set
CONFIG_LWIP_LOCAL_HOSTNAME="lolin-c3-pico"
# end of LWIP

View file

@ -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

View file

@ -7,6 +7,7 @@
#
# LWIP
#
# CONFIG_LWIP_IPV6 is not set
CONFIG_LWIP_LOCAL_HOSTNAME="waveshare-esp32-s3-tiny"
# end of LWIP

View file

@ -11,6 +11,8 @@
#include "py/mperrno.h"
#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"
@ -25,6 +27,24 @@
#include "components/lwip/lwip/src/include/lwip/netdb.h"
#include "components/vfs/include/esp_vfs_eventfd.h"
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 = family,
.ai_socktype = 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);
}
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:
@ -175,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;
@ -230,8 +250,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);
@ -244,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();
@ -257,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;
}
@ -295,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
@ -321,20 +347,35 @@ socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_o
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 = "<broadcast>";
uint32_t ip;
if (hostlen == 0) {
ip = IPADDR_ANY;
} else if (hostlen == strlen(broadcast) &&
memcmp(host, broadcast, strlen(broadcast)) == 0) {
ip = IPADDR_BROADCAST;
} else {
ip = inet_addr(host);
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);
// 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
#endif
{
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 = AF_INET;
bind_addr.sin_port = htons(port);
int result = lwip_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr));
if (result == 0) {
@ -376,26 +417,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,
};
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 -----
@ -403,7 +426,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.
@ -483,9 +506,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
@ -507,10 +530,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);
}
@ -519,6 +539,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;
}
@ -605,29 +629,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 = AF_INET,
.ai_socktype = SOCK_STREAM,
};
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();
}
struct sockaddr_storage addr;
resolve_host_or_throw(self, host, &addr, port);
// 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);
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;

View file

@ -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,37 +23,102 @@ 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) {
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
// 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);
}
}
const struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo *res;
int err = lwip_getaddrinfo(host, NULL, &hints, &res);
if (err != 0 || res == NULL) {
return mp_const_none;
}
char service_buf[6];
snprintf(service_buf, sizeof(service_buf), "%d", service);
#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);
return ip_obj;
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));
}
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);
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) {
const struct addrinfo hints = {
.ai_flags = flags,
.ai_family = family,
.ai_protocol = proto,
.ai_socktype = type,
};
struct addrinfo *res = NULL;
int err = socketpool_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));
}
}

View file

@ -6,8 +6,7 @@
#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);
void socketpool_resolve_host_or_throw(int family, int type, const char *hostname, struct sockaddr_storage *addr, int port);

View file

@ -13,15 +13,23 @@
#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"
#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"
#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 +453,44 @@ 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);
}
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;
#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);
}
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;
@ -476,6 +522,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),
@ -489,12 +538,31 @@ 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
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));
}
#else
if (ipv6) {
mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_ipv6);
}
#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) {
@ -568,11 +636,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) &&
@ -589,3 +657,38 @@ 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_empty_tuple;
}
esp_netif_get_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &self->dns_info);
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_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;
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);
}

View file

@ -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"
@ -27,6 +28,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
@ -232,14 +235,16 @@ 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);
#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);
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) {
@ -255,3 +260,94 @@ 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 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
#endif
{
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));
}
mp_obj_t sockaddr_to_tuple(const struct sockaddr_storage *sockaddr) {
mp_obj_t args[4] = {
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
#endif
{
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) {
#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));
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));
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
#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));
espaddr->type = ESP_IPADDR_TYPE_V4;
}
}
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
#endif
{
struct sockaddr_in *addr = (void *)sockaddr;
memcpy(&addr->sin_addr, &espaddr->u_addr.ip4.addr, sizeof(espaddr->u_addr.ip4.addr));
}
}

View file

@ -11,7 +11,17 @@
#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 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);
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);

View file

@ -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

View file

@ -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

View file

@ -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) {

View file

@ -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;

View file

@ -5,10 +5,12 @@
// 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"
#include "shared-bindings/wifi/__init__.h"
#include "shared-bindings/ipaddress/__init__.h"
#include "lwip/dns.h"
#include "lwip/inet.h"
@ -21,72 +23,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) {
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(self, host, &addr);
socketpool_resolve_host_raise(host, &addr);
char ip_str[IP4ADDR_STRLEN_MAX];
inet_ntoa_r(addr, ip_str, IP4ADDR_STRLEN_MAX);
@ -94,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);
}

View file

@ -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);

View file

@ -4,10 +4,78 @@
//
// SPDX-License-Identifier: MIT
#include "shared-bindings/socketpool/__init__.h"
#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);
}
}

View file

@ -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);

View file

@ -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"
@ -405,8 +406,15 @@ 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);
}
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) {
@ -481,7 +489,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
@ -522,3 +534,47 @@ 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_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;
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);
}

View file

@ -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)

View file

@ -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);

View file

@ -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,

View file

@ -142,28 +142,14 @@ 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);
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);
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);
}
static MP_DEFINE_CONST_FUN_OBJ_KW(socketpool_socketpool_getaddrinfo_obj, 1, socketpool_socketpool_getaddrinfo);
@ -207,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;

View file

@ -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,
@ -32,3 +26,5 @@ 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);
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);

View file

@ -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
//|
//| <p>
//| <details>
//| <summary>AF_INET6 (IPv6) supported on these boards</summary>
//| <ul>
//| {% for board in support_matrix_reverse["socketpool.socketpool.AF_INET6"] %}
//| <li> {{ board }}
//| {% endfor %}
//| </ul>
//| </details>
//| </p>
//| """
static const mp_rom_map_elem_t socketpool_globals_table[] = {

View file

@ -596,6 +596,26 @@ 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);
//| 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_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);
//| 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) {
@ -634,6 +654,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: 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);
}
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) {
@ -655,14 +693,29 @@ 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 = True, ipv6: bool = False) -> None:
//| """Starts the station DHCP client.
//|
//| 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(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 = 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."""
@ -772,6 +825,10 @@ static const mp_rom_map_elem_t wifi_radio_locals_dict_table[] = {
{ 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) },
};

View file

@ -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);
@ -105,6 +105,12 @@ 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_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);

View file

@ -13,8 +13,9 @@
//| """
//| 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.
//| """
//| radio: Radio
//| """Wifi radio used to manage both station and AP modes.
//| This object is the sole instance of `wifi.Radio`."""

View file

@ -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);
@ -1592,12 +1596,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;