Skip to content

Commit bffdf3b

Browse files
authored
Merge pull request #9436 from jepler/veesix
Add IPv6 support for Espressif
2 parents 3865456 + 21a5c93 commit bffdf3b

File tree

31 files changed

+733
-268
lines changed

31 files changed

+733
-268
lines changed

docs/shared_bindings_matrix.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
"sys": "CIRCUITPY_SYS",
8686
"terminalio": "CIRCUITPY_DISPLAYIO",
8787
"usb": "CIRCUITPY_PYUSB",
88+
"socketpool.socketpool.AF_INET6": "CIRCUITPY_SOCKETPOOL_IPV6",
8889
}
8990

9091
MODULES_NOT_IN_BINDINGS = ["binascii", "errno", "json", "re", "ulab"]

locale/circuitpython.pot

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1562,7 +1562,6 @@ msgstr ""
15621562
msgid "Only IPv4 addresses supported"
15631563
msgstr ""
15641564

1565-
#: ports/espressif/common-hal/socketpool/Socket.c
15661565
#: ports/raspberrypi/common-hal/socketpool/Socket.c
15671566
msgid "Only IPv4 sockets supported"
15681567
msgstr ""
@@ -2224,6 +2223,10 @@ msgstr ""
22242223
msgid "Unsupported hash algorithm"
22252224
msgstr ""
22262225

2226+
#: ports/espressif/common-hal/socketpool/Socket.c
2227+
msgid "Unsupported socket type"
2228+
msgstr ""
2229+
22272230
#: ports/espressif/common-hal/_bleio/Adapter.c
22282231
#: ports/espressif/common-hal/dualbank/__init__.c
22292232
msgid "Update failed"

ports/espressif/boards/lolin_c3_pico/mpconfigboard.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,8 @@ CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1
1111

1212
CIRCUITPY_ESP_USB_SERIAL_JTAG = 1
1313

14+
# Not enough flash
15+
CIRCUITPY_SOCKETPOOL_IPV6 = 0
16+
1417
# Include these Python libraries in firmware.
1518
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel

ports/espressif/boards/lolin_c3_pico/sdkconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#
88
# LWIP
99
#
10+
# CONFIG_LWIP_IPV6 is not set
1011
CONFIG_LWIP_LOCAL_HOSTNAME="lolin-c3-pico"
1112
# end of LWIP
1213

ports/espressif/boards/waveshare_esp32_s3_tiny/mpconfigboard.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ CIRCUITPY_ESP_FLASH_SIZE = 4MB
1212
CIRCUITPY_ESP_PSRAM_SIZE = 2MB
1313
CIRCUITPY_ESP_PSRAM_MODE = qio
1414
CIRCUITPY_ESP_PSRAM_FREQ = 80m
15+
16+
# Not enough flash
17+
CIRCUITPY_SOCKETPOOL_IPV6 = 0

ports/espressif/boards/waveshare_esp32_s3_tiny/sdkconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#
88
# LWIP
99
#
10+
# CONFIG_LWIP_IPV6 is not set
1011
CONFIG_LWIP_LOCAL_HOSTNAME="waveshare-esp32-s3-tiny"
1112
# end of LWIP
1213

ports/espressif/common-hal/socketpool/Socket.c

Lines changed: 81 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include "py/mperrno.h"
1212
#include "py/runtime.h"
1313
#include "shared-bindings/socketpool/SocketPool.h"
14+
#include "common-hal/socketpool/__init__.h"
15+
#include "common-hal/wifi/__init__.h"
1416
#if CIRCUITPY_SSL
1517
#include "shared-bindings/ssl/SSLSocket.h"
1618
#include "shared-module/ssl/SSLSocket.h"
@@ -25,6 +27,24 @@
2527
#include "components/lwip/lwip/src/include/lwip/netdb.h"
2628
#include "components/vfs/include/esp_vfs_eventfd.h"
2729

30+
void socketpool_resolve_host_or_throw(int family, int type, const char *hostname, struct sockaddr_storage *addr, int port) {
31+
struct addrinfo *result_i;
32+
const struct addrinfo hints = {
33+
.ai_family = family,
34+
.ai_socktype = type,
35+
};
36+
int error = socketpool_getaddrinfo_common(hostname, port, &hints, &result_i);
37+
if (error != 0 || result_i == NULL) {
38+
common_hal_socketpool_socketpool_raise_gaierror_noname();
39+
}
40+
memcpy(addr, result_i->ai_addr, sizeof(struct sockaddr_storage));
41+
lwip_freeaddrinfo(result_i);
42+
}
43+
44+
static void resolve_host_or_throw(socketpool_socket_obj_t *self, const char *hostname, struct sockaddr_storage *addr, int port) {
45+
socketpool_resolve_host_or_throw(self->family, self->type, hostname, addr, port);
46+
}
47+
2848
StackType_t socket_select_stack[2 * configMINIMAL_STACK_SIZE];
2949

3050
/* Socket state table:
@@ -175,7 +195,7 @@ static bool _socketpool_socket(socketpool_socketpool_obj_t *self,
175195
if (family == SOCKETPOOL_AF_INET) {
176196
addr_family = AF_INET;
177197
ipproto = IPPROTO_IP;
178-
#if LWIP_IPV6
198+
#if CIRCUITPY_SOCKETPOOL_IPV6
179199
} else { // INET6
180200
addr_family = AF_INET6;
181201
ipproto = IPPROTO_IPV6;
@@ -230,8 +250,14 @@ bool socketpool_socket(socketpool_socketpool_obj_t *self,
230250

231251
socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_t *self,
232252
socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type, int proto) {
233-
if (family != SOCKETPOOL_AF_INET) {
234-
mp_raise_NotImplementedError(MP_ERROR_TEXT("Only IPv4 sockets supported"));
253+
switch (family) {
254+
#if CIRCUITPY_SOCKETPOOL_IPV6
255+
case SOCKETPOOL_AF_INET6:
256+
#endif
257+
case SOCKETPOOL_AF_INET:
258+
break;
259+
default:
260+
mp_raise_NotImplementedError(MP_ERROR_TEXT("Unsupported socket type"));
235261
}
236262

237263
socketpool_socket_obj_t *sock = m_new_obj_with_finaliser(socketpool_socket_obj_t);
@@ -244,9 +270,9 @@ socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_
244270
return sock;
245271
}
246272

247-
int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_t *port, socketpool_socket_obj_t *accepted) {
248-
struct sockaddr_in accept_addr;
249-
socklen_t socklen = sizeof(accept_addr);
273+
int socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out, socketpool_socket_obj_t *accepted) {
274+
struct sockaddr_storage peer_addr;
275+
socklen_t socklen = sizeof(peer_addr);
250276
int newsoc = -1;
251277
bool timed_out = false;
252278
uint64_t start_ticks = supervisor_ticks_ms64();
@@ -257,20 +283,17 @@ int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_
257283
timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms;
258284
}
259285
RUN_BACKGROUND_TASKS;
260-
newsoc = lwip_accept(self->num, (struct sockaddr *)&accept_addr, &socklen);
286+
newsoc = lwip_accept(self->num, (struct sockaddr *)&peer_addr, &socklen);
261287
// In non-blocking mode, fail instead of timing out
262288
if (newsoc == -1 && (self->timeout_ms == 0 || mp_hal_is_interrupted())) {
263289
return -MP_EAGAIN;
264290
}
265291
}
266292

267-
if (!timed_out) {
268-
// harmless on failure but avoiding memcpy is faster
269-
memcpy((void *)ip, (void *)&accept_addr.sin_addr.s_addr, sizeof(accept_addr.sin_addr.s_addr));
270-
*port = accept_addr.sin_port;
271-
} else {
293+
if (timed_out) {
272294
return -ETIMEDOUT;
273295
}
296+
274297
if (newsoc < 0) {
275298
return -MP_EBADF;
276299
}
@@ -295,13 +318,16 @@ int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_
295318
accepted->type = self->type;
296319
}
297320

321+
if (peer_out) {
322+
*peer_out = sockaddr_to_tuple(&peer_addr);
323+
}
324+
298325
return newsoc;
299326
}
300327

301-
socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *self,
302-
uint8_t *ip, uint32_t *port) {
328+
socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out) {
303329
socketpool_socket_obj_t *sock = m_new_obj_with_finaliser(socketpool_socket_obj_t);
304-
int newsoc = socketpool_socket_accept(self, ip, port, NULL);
330+
int newsoc = socketpool_socket_accept(self, peer_out, NULL);
305331

306332
if (newsoc > 0) {
307333
// Create the socket
@@ -321,20 +347,35 @@ socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_o
321347

322348
size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self,
323349
const char *host, size_t hostlen, uint32_t port) {
324-
struct sockaddr_in bind_addr;
350+
struct sockaddr_storage bind_addr;
325351
const char *broadcast = "<broadcast>";
326-
uint32_t ip;
327-
if (hostlen == 0) {
328-
ip = IPADDR_ANY;
329-
} else if (hostlen == strlen(broadcast) &&
330-
memcmp(host, broadcast, strlen(broadcast)) == 0) {
331-
ip = IPADDR_BROADCAST;
332-
} else {
333-
ip = inet_addr(host);
352+
353+
bind_addr.ss_family = self->family;
354+
355+
#if CIRCUITPY_SOCKETPOOL_IPV6
356+
if (self->family == AF_INET6) {
357+
struct sockaddr_in6 *addr6 = (void *)&bind_addr;
358+
addr6->sin6_port = htons(port);
359+
// no ipv6 broadcast
360+
if (hostlen == 0) {
361+
memset(&addr6->sin6_addr, 0, sizeof(addr6->sin6_addr));
362+
} else {
363+
socketpool_resolve_host_or_throw(self->family, self->type, host, &bind_addr, port);
364+
}
365+
} else
366+
#endif
367+
{
368+
struct sockaddr_in *addr4 = (void *)&bind_addr;
369+
addr4->sin_port = htons(port);
370+
if (hostlen == 0) {
371+
addr4->sin_addr.s_addr = IPADDR_ANY;
372+
} else if (hostlen == strlen(broadcast) &&
373+
memcmp(host, broadcast, strlen(broadcast)) == 0) {
374+
addr4->sin_addr.s_addr = IPADDR_BROADCAST;
375+
} else {
376+
socketpool_resolve_host_or_throw(self->family, self->type, host, &bind_addr, port);
377+
}
334378
}
335-
bind_addr.sin_addr.s_addr = ip;
336-
bind_addr.sin_family = AF_INET;
337-
bind_addr.sin_port = htons(port);
338379

339380
int result = lwip_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr));
340381
if (result == 0) {
@@ -376,34 +417,16 @@ void common_hal_socketpool_socket_close(socketpool_socket_obj_t *self) {
376417

377418
void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self,
378419
const char *host, size_t hostlen, uint32_t port) {
379-
const struct addrinfo hints = {
380-
.ai_family = AF_INET,
381-
.ai_socktype = SOCK_STREAM,
382-
};
383-
struct addrinfo *result_i;
384-
int error = lwip_getaddrinfo(host, NULL, &hints, &result_i);
385-
if (error != 0 || result_i == NULL) {
386-
common_hal_socketpool_socketpool_raise_gaierror_noname();
387-
}
388-
389-
// Set parameters
390-
struct sockaddr_in dest_addr;
391-
#pragma GCC diagnostic push
392-
#pragma GCC diagnostic ignored "-Wcast-align"
393-
dest_addr.sin_addr.s_addr = ((struct sockaddr_in *)result_i->ai_addr)->sin_addr.s_addr;
394-
#pragma GCC diagnostic pop
395-
lwip_freeaddrinfo(result_i);
396-
397-
dest_addr.sin_family = AF_INET;
398-
dest_addr.sin_port = htons(port);
420+
struct sockaddr_storage addr;
421+
resolve_host_or_throw(self, host, &addr, port);
399422

400423
// Replace above with function call -----
401424

402425
// Emulate SO_CONTIMEO, which is not implemented by lwip.
403426
// All our sockets are non-blocking, so we check the timeout ourselves.
404427

405428
int result = -1;
406-
result = lwip_connect(self->num, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in));
429+
result = lwip_connect(self->num, (struct sockaddr *)&addr, addr.s2_len);
407430

408431
if (result == 0) {
409432
// Connected immediately.
@@ -483,9 +506,9 @@ bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *self, int back
483506
}
484507

485508
mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *self,
486-
uint8_t *buf, uint32_t len, uint8_t *ip, uint32_t *port) {
509+
uint8_t *buf, uint32_t len, mp_obj_t *source_out) {
487510

488-
struct sockaddr_in source_addr;
511+
struct sockaddr_storage source_addr;
489512
socklen_t socklen = sizeof(source_addr);
490513

491514
// LWIP Socket
@@ -507,10 +530,7 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *se
507530
}
508531
}
509532

510-
if (!timed_out) {
511-
memcpy((void *)ip, (void *)&source_addr.sin_addr.s_addr, sizeof(source_addr.sin_addr.s_addr));
512-
*port = htons(source_addr.sin_port);
513-
} else {
533+
if (timed_out) {
514534
mp_raise_OSError(ETIMEDOUT);
515535
}
516536

@@ -519,6 +539,10 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *se
519539
return 0;
520540
}
521541

542+
if (source_out) {
543+
*source_out = sockaddr_to_tuple(&source_addr);
544+
}
545+
522546
return received;
523547
}
524548

@@ -605,29 +629,10 @@ mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t *self, const
605629
mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *self,
606630
const char *host, size_t hostlen, uint32_t port, const uint8_t *buf, uint32_t len) {
607631

608-
// Set parameters
609-
const struct addrinfo hints = {
610-
.ai_family = AF_INET,
611-
.ai_socktype = SOCK_STREAM,
612-
};
613-
struct addrinfo *result_i;
614-
int error = lwip_getaddrinfo(host, NULL, &hints, &result_i);
615-
if (error != 0 || result_i == NULL) {
616-
common_hal_socketpool_socketpool_raise_gaierror_noname();
617-
}
618-
619-
// Set parameters
620-
struct sockaddr_in dest_addr;
621-
#pragma GCC diagnostic push
622-
#pragma GCC diagnostic ignored "-Wcast-align"
623-
dest_addr.sin_addr.s_addr = ((struct sockaddr_in *)result_i->ai_addr)->sin_addr.s_addr;
624-
#pragma GCC diagnostic pop
625-
lwip_freeaddrinfo(result_i);
626-
627-
dest_addr.sin_family = AF_INET;
628-
dest_addr.sin_port = htons(port);
632+
struct sockaddr_storage addr;
633+
resolve_host_or_throw(self, host, &addr, port);
629634

630-
int bytes_sent = lwip_sendto(self->num, buf, len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
635+
int bytes_sent = lwip_sendto(self->num, buf, len, 0, (struct sockaddr *)&addr, addr.s2_len);
631636
if (bytes_sent < 0) {
632637
mp_raise_BrokenPipeError();
633638
return 0;

0 commit comments

Comments
 (0)