Skip to content

Commit a7a1bd7

Browse files
committed
Implement DNS resolution
``` >>> s = socketpool.SocketPool(wifi.radio) >>> s.getaddrinfo("google.com", 80) [(0, 0, 0, '', ('142.250.81.206', 80))] ```
1 parent 6c3cdce commit a7a1bd7

File tree

12 files changed

+446
-12
lines changed

12 files changed

+446
-12
lines changed

ports/raspberrypi/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ SRC_SDK_CYW43 := \
7979
src/rp2_common/pico_lwip/random.c \
8080

8181
SRC_LWIP := \
82+
shared/netutils/netutils.c \
8283
$(wildcard sdk/lib/lwip/src/core/*.c) \
8384
$(wildcard sdk/lib/lwip/src/core/ipv4/*.c) \
8485
sdk/lib/lwip/src/netif/ethernet.c \

ports/raspberrypi/boards/raspberry_pi_pico_w/mpconfigboard.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ CIRCUITPY_SSL = 0
1515
CIRCUITPY_HASHLIB = 0
1616
CIRCUITPY_WEB_WORKFLOW = 0
1717
CIRCUITPY_MDNS = 0
18-
CIRCUITPY_SOCKETPOOL = 0
18+
CIRCUITPY_SOCKETPOOL = 1
1919
CIRCUITPY_WIFI = 1
2020

2121
CFLAGS += -DCYW43_PIN_WL_HOST_WAKE=24 -DCYW43_PIN_WL_REG_ON=23 -DCYW43_WL_GPIO_COUNT=3 -DCYW43_WL_GPIO_LED_PIN=0
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Lucian Copeland for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "shared-bindings/socketpool/Socket.h"
28+
29+
#include "shared/runtime/interrupt_char.h"
30+
#include "py/mperrno.h"
31+
#include "py/runtime.h"
32+
#include "shared-bindings/socketpool/SocketPool.h"
33+
#include "supervisor/port.h"
34+
#include "supervisor/shared/tick.h"
35+
#include "supervisor/workflow.h"
36+
37+
#include "lwip/err.h"
38+
#include "lwip/sys.h"
39+
#include "lwip/netdb.h"
40+
41+
#define MAX_SOCKETS (8)
42+
43+
STATIC mp_obj_t open_socket_objs[MAX_SOCKETS];
44+
STATIC bool user_socket[MAX_SOCKETS];
45+
46+
void socket_user_reset(void) {
47+
for (size_t i = 0; i < MP_ARRAY_SIZE(open_socket_objs); i++) {
48+
if (open_socket_objs[i] && user_socket[i]) {
49+
// shut 'er down
50+
}
51+
}
52+
}
53+
54+
// The writes below send an event to the socket select task so that it redoes the
55+
// select with the new open socket set.
56+
57+
STATIC bool register_open_socket(mp_obj_t obj) {
58+
for (size_t i = 0; i < MP_ARRAY_SIZE(open_socket_objs); i++) {
59+
if (!open_socket_objs[i]) {
60+
open_socket_objs[i] = obj;
61+
user_socket[i] = false;
62+
return true;
63+
}
64+
}
65+
return false;
66+
}
67+
68+
STATIC void unregister_open_socket(mp_obj_t obj) {
69+
for (size_t i = 0; i < MP_ARRAY_SIZE(open_socket_objs); i++) {
70+
if (open_socket_objs[i] == obj) {
71+
open_socket_objs[i] = NULL;
72+
user_socket[i] = false;
73+
}
74+
}
75+
}
76+
77+
STATIC void mark_user_socket(mp_obj_t obj) {
78+
for (size_t i = 0; i < MP_ARRAY_SIZE(open_socket_objs); i++) {
79+
if (open_socket_objs[i] == obj) {
80+
user_socket[i] = true;
81+
return;
82+
}
83+
}
84+
}
85+
86+
bool socketpool_socket(socketpool_socketpool_obj_t *self,
87+
socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type,
88+
socketpool_socket_obj_t *sock) {
89+
mp_raise_NotImplementedError(NULL);
90+
}
91+
92+
socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_t *self,
93+
socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type) {
94+
mp_raise_NotImplementedError(NULL);
95+
}
96+
97+
int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_t *port) {
98+
mp_raise_NotImplementedError(NULL);
99+
}
100+
101+
socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *self,
102+
uint8_t *ip, uint32_t *port) {
103+
mp_raise_NotImplementedError(NULL);
104+
}
105+
106+
bool common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self,
107+
const char *host, size_t hostlen, uint32_t port) {
108+
mp_raise_NotImplementedError(NULL);
109+
}
110+
111+
void socketpool_socket_close(socketpool_socket_obj_t *self) {
112+
mp_raise_NotImplementedError(NULL);
113+
}
114+
115+
void common_hal_socketpool_socket_close(socketpool_socket_obj_t *self) {
116+
mp_raise_NotImplementedError(NULL);
117+
}
118+
119+
void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self,
120+
const char *host, size_t hostlen, uint32_t port) {
121+
mp_raise_NotImplementedError(NULL);
122+
}
123+
124+
bool common_hal_socketpool_socket_get_closed(socketpool_socket_obj_t *self) {
125+
mp_raise_NotImplementedError(NULL);
126+
}
127+
128+
bool common_hal_socketpool_socket_get_connected(socketpool_socket_obj_t *self) {
129+
mp_raise_NotImplementedError(NULL);
130+
}
131+
132+
bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *self, int backlog) {
133+
mp_raise_NotImplementedError(NULL);
134+
}
135+
136+
mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *self,
137+
uint8_t *buf, uint32_t len, uint8_t *ip, uint32_t *port) {
138+
mp_raise_NotImplementedError(NULL);
139+
}
140+
141+
int socketpool_socket_recv_into(socketpool_socket_obj_t *self,
142+
const uint8_t *buf, uint32_t len) {
143+
mp_raise_NotImplementedError(NULL);
144+
}
145+
146+
mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len) {
147+
mp_raise_NotImplementedError(NULL);
148+
}
149+
150+
int socketpool_socket_send(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len) {
151+
mp_raise_NotImplementedError(NULL);
152+
}
153+
154+
mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len) {
155+
mp_raise_NotImplementedError(NULL);
156+
}
157+
158+
mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *self,
159+
const char *host, size_t hostlen, uint32_t port, const uint8_t *buf, uint32_t len) {
160+
mp_raise_NotImplementedError(NULL);
161+
}
162+
163+
void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t *self, uint32_t timeout_ms) {
164+
mp_raise_NotImplementedError(NULL);
165+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2013-2019 Damien P. George
7+
* Copyright (c) 2015 Galen Hazelwood
8+
* Copyright (c) 2015-2017 Paul Sokolovsky
9+
* Copyright (c) 2022 Jeff Epler for Adafruit Industries
10+
*
11+
* Permission is hereby granted, free of charge, to any person obtaining a copy
12+
* of this software and associated documentation files (the "Software"), to deal
13+
* in the Software without restriction, including without limitation the rights
14+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15+
* copies of the Software, and to permit persons to whom the Software is
16+
* furnished to do so, subject to the following conditions:
17+
*
18+
* The above copyright notice and this permission notice shall be included in
19+
* all copies or substantial portions of the Software.
20+
*
21+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27+
* THE SOFTWARE.
28+
*/
29+
30+
#pragma once
31+
32+
#include "py/obj.h"
33+
34+
#include "common-hal/socketpool/SocketPool.h"
35+
36+
typedef struct _lwip_socket_obj_t {
37+
mp_obj_base_t base;
38+
39+
volatile union {
40+
struct tcp_pcb *tcp;
41+
struct udp_pcb *udp;
42+
struct raw_pcb *raw;
43+
} pcb;
44+
volatile union {
45+
struct pbuf *pbuf;
46+
struct {
47+
uint8_t alloc;
48+
uint8_t iget;
49+
uint8_t iput;
50+
union {
51+
struct tcp_pcb *item; // if alloc == 0
52+
struct tcp_pcb **array; // if alloc != 0
53+
} tcp;
54+
} connection;
55+
} incoming;
56+
mp_obj_t callback;
57+
byte peer[4];
58+
mp_uint_t peer_port;
59+
mp_uint_t timeout;
60+
uint16_t recv_offset;
61+
62+
uint8_t domain;
63+
uint8_t type;
64+
65+
#define STATE_NEW 0
66+
#define STATE_LISTENING 1
67+
#define STATE_CONNECTING 2
68+
#define STATE_CONNECTED 3
69+
#define STATE_PEER_CLOSED 4
70+
#define STATE_ACTIVE_UDP 5
71+
// Negative value is lwIP error
72+
int8_t state;
73+
74+
socketpool_socketpool_obj_t *pool;
75+
} socketpool_socket_obj_t;
76+
77+
void socket_user_reset(void);
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "shared-bindings/socketpool/SocketPool.h"
28+
#include "common-hal/socketpool/Socket.h"
29+
#include "shared/runtime/interrupt_char.h"
30+
#include "py/runtime.h"
31+
#include "shared-bindings/wifi/__init__.h"
32+
33+
#include "lwip/dns.h"
34+
#include "lwip/inet.h"
35+
36+
void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *self, mp_obj_t radio) {
37+
if (radio != MP_OBJ_FROM_PTR(&common_hal_wifi_radio_obj)) {
38+
mp_raise_ValueError(translate("SocketPool can only be used with wifi.radio"));
39+
}
40+
}
41+
42+
// common_hal_socketpool_socket is in socketpool/Socket.c to centralize open socket tracking.
43+
44+
typedef struct _getaddrinfo_state_t {
45+
volatile int status;
46+
volatile ip_addr_t ipaddr;
47+
} getaddrinfo_state_t;
48+
49+
STATIC void lwip_getaddrinfo_cb(const char *name, const ip_addr_t *ipaddr, void *arg) {
50+
getaddrinfo_state_t *state = arg;
51+
if (ipaddr != NULL) {
52+
state->status = 1;
53+
state->ipaddr = *ipaddr;
54+
} else {
55+
// error
56+
state->status = -2;
57+
}
58+
}
59+
60+
mp_obj_t common_hal_socketpool_socketpool_gethostbyname(socketpool_socketpool_obj_t *self,
61+
const char *host) {
62+
63+
getaddrinfo_state_t state;
64+
state.status = 0;
65+
66+
MICROPY_PY_LWIP_ENTER
67+
err_t ret = dns_gethostbyname(host, (ip_addr_t *)&state.ipaddr, lwip_getaddrinfo_cb, &state);
68+
MICROPY_PY_LWIP_EXIT
69+
70+
switch (ret) {
71+
case ERR_OK:
72+
// cached
73+
state.status = 1;
74+
break;
75+
case ERR_INPROGRESS:
76+
while (state.status == 0) {
77+
RUN_BACKGROUND_TASKS;
78+
if (mp_hal_is_interrupted()) {
79+
break;
80+
}
81+
}
82+
break;
83+
default:
84+
state.status = ret;
85+
}
86+
87+
if (state.status < 0) {
88+
// TODO: CPython raises gaierror, we raise with native lwIP negative error
89+
// values, to differentiate from normal errno's at least in such way.
90+
mp_raise_OSError(state.status);
91+
}
92+
93+
char ip_str[IP4ADDR_STRLEN_MAX];
94+
inet_ntoa_r(state.ipaddr, ip_str, IP4ADDR_STRLEN_MAX);
95+
mp_obj_t ip_obj = mp_obj_new_str(ip_str, strlen(ip_str));
96+
return ip_obj;
97+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#pragma once
28+
29+
#include "py/obj.h"
30+
31+
typedef struct {
32+
mp_obj_base_t base;
33+
} socketpool_socketpool_obj_t;

0 commit comments

Comments
 (0)