Skip to content

Commit 37a8c1c

Browse files
committed
Complete non-blocking implementations, add socket close checking
1 parent 4cdb298 commit 37a8c1c

File tree

5 files changed

+143
-38
lines changed

5 files changed

+143
-38
lines changed

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

Lines changed: 133 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,32 @@
3838
#include "components/lwip/lwip/src/include/lwip/sys.h"
3939
#include "components/lwip/lwip/src/include/lwip/netdb.h"
4040

41+
STATIC socketpool_socket_obj_t * open_socket_handles[CONFIG_LWIP_MAX_SOCKETS]; // 4 on the wrover/wroom
42+
43+
void socket_reset(void) {
44+
for (size_t i = 0; i < MP_ARRAY_SIZE(open_socket_handles); i++) {
45+
if (open_socket_handles[i]) {
46+
if (open_socket_handles[i]->num > 0) {
47+
common_hal_socketpool_socket_close(open_socket_handles[i]);
48+
open_socket_handles[i] = NULL;
49+
} else {
50+
// accidentally got a TCP socket in here, or something.
51+
open_socket_handles[i] = NULL;
52+
}
53+
}
54+
}
55+
}
56+
57+
bool register_open_socket(socketpool_socket_obj_t* self) {
58+
for (size_t i = 0; i < MP_ARRAY_SIZE(open_socket_handles); i++) {
59+
if (open_socket_handles[i] == NULL) {
60+
open_socket_handles[i] = self;
61+
return true;
62+
}
63+
}
64+
return false;
65+
}
66+
4167
STATIC void _lazy_init_LWIP(socketpool_socket_obj_t* self) {
4268
if (self->num != -1) {
4369
return; //safe to call on existing socket
@@ -47,7 +73,7 @@ STATIC void _lazy_init_LWIP(socketpool_socket_obj_t* self) {
4773
}
4874
int socknum = -1;
4975
socknum = lwip_socket(self->family, self->type, self->ipproto);
50-
if (socknum < 0) {
76+
if (socknum < 0 || !register_open_socket(self)) {
5177
mp_raise_RuntimeError(translate("Out of sockets"));
5278
}
5379
self->num = socknum;
@@ -78,34 +104,74 @@ bool common_hal_socketpool_socket_bind(socketpool_socket_obj_t* self,
78104
bind_addr.sin_family = AF_INET;
79105
bind_addr.sin_port = htons(port);
80106

81-
return lwip_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr)) == 0;
107+
int opt = 1;
108+
int err = lwip_setsockopt(self->num, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
109+
if (err != 0) {
110+
mp_raise_RuntimeError(translate("Issue setting SO_REUSEADDR"));
111+
}
112+
int result = lwip_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr)) == 0;
113+
return result;
82114
}
83115

84116
bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t* self, int backlog) {
85117
return lwip_listen(self->num, backlog) == 0;
86118
}
87119

88-
int common_hal_socketpool_socket_accept(socketpool_socket_obj_t* self,
120+
socketpool_socket_obj_t* common_hal_socketpool_socket_accept(socketpool_socket_obj_t* self,
89121
uint8_t* ip, uint *port) {
90122
struct sockaddr_in accept_addr;
91123
socklen_t socklen = sizeof(accept_addr);
92-
93124
int newsoc = -1;
94-
//(self->timeout_ms == 0 || supervisor_ticks_ms64() - start_ticks <= self->timeout_ms)
95-
while ((newsoc == -1) && !mp_hal_is_interrupted() ) {
125+
bool timed_out = false;
126+
uint64_t start_ticks = supervisor_ticks_ms64();
127+
128+
if (self->timeout_ms != (uint)-1) {
129+
mp_printf(&mp_plat_print, "will timeout");
130+
} else {
131+
mp_printf(&mp_plat_print, "won't timeout");
132+
}
133+
134+
// Allow timeouts and interrupts
135+
while (newsoc == -1 &&
136+
!timed_out &&
137+
!mp_hal_is_interrupted()) {
138+
if (self->timeout_ms != (uint)-1) {
139+
timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms;
140+
}
96141
RUN_BACKGROUND_TASKS;
97142
newsoc = lwip_accept(self->num, (struct sockaddr *)&accept_addr, &socklen);
143+
// In non-blocking mode, fail instead of looping
144+
if (newsoc == -1 && self->timeout_ms == 0) {
145+
mp_raise_OSError(MP_EAGAIN);
146+
}
98147
}
99-
mp_printf(&mp_plat_print, "oldsoc:%d newsoc:%d\n",self->num, newsoc);
100148

101-
memcpy((void *)ip, (void*)&accept_addr.sin_addr.s_addr, sizeof(accept_addr.sin_addr.s_addr));
102-
*port = accept_addr.sin_port;
149+
if (!timed_out) {
150+
// harmless on failure but avoiding memcpy is faster
151+
memcpy((void *)ip, (void*)&accept_addr.sin_addr.s_addr, sizeof(accept_addr.sin_addr.s_addr));
152+
*port = accept_addr.sin_port;
153+
} else {
154+
mp_raise_OSError(ETIMEDOUT);
155+
}
103156

104157
if (newsoc > 0) {
158+
// Create the socket
159+
socketpool_socket_obj_t *sock = m_new_obj_with_finaliser(socketpool_socket_obj_t);
160+
sock->base.type = &socketpool_socket_type;
161+
sock->num = newsoc;
162+
sock->tls = NULL;
163+
sock->ssl_context = NULL;
164+
sock->pool = self->pool;
165+
166+
if (!register_open_socket(sock)) {
167+
mp_raise_OSError(MP_EBADF);
168+
}
169+
105170
lwip_fcntl(newsoc, F_SETFL, O_NONBLOCK);
106-
return newsoc;
171+
return sock;
107172
} else {
108-
return 0;
173+
mp_raise_OSError(MP_EBADF);
174+
return NULL;
109175
}
110176
}
111177

@@ -158,9 +224,10 @@ bool common_hal_socketpool_socket_get_connected(socketpool_socket_obj_t* self) {
158224
}
159225

160226
mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len) {
161-
size_t sent = -1;
227+
int sent = -1;
162228
if (self->num != -1) {
163229
// LWIP Socket
230+
// TODO: deal with potential failure/add timeout?
164231
sent = lwip_send(self->num, buf, len, 0);
165232
} else if (self->tls != NULL) {
166233
// TLS Socket
@@ -174,15 +241,27 @@ mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const
174241
}
175242

176243
mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len) {
177-
size_t received = 0;
244+
int received = 0;
245+
bool timed_out = false;
178246

179247
if (self->num != -1) {
180248
// LWIP Socket
181-
mp_printf(&mp_plat_print, "lwip_recv:\n");
182-
183-
received = lwip_recv(self->num, (void*) buf, len - 1, 0);
184-
mp_printf(&mp_plat_print, "received:%d\n",received);
249+
uint64_t start_ticks = supervisor_ticks_ms64();
250+
received = -1;
251+
while (received == -1 &&
252+
!timed_out &&
253+
!mp_hal_is_interrupted()) {
254+
if (self->timeout_ms != (uint)-1) {
255+
timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms;
256+
}
257+
RUN_BACKGROUND_TASKS;
258+
received = lwip_recv(self->num, (void*) buf, len - 1, 0);
185259

260+
// In non-blocking mode, fail instead of looping
261+
if (received == -1 && self->timeout_ms == 0) {
262+
mp_raise_OSError(MP_EAGAIN);
263+
}
264+
}
186265
} else if (self->tls != NULL) {
187266
// TLS Socket
188267
int status = 0;
@@ -194,8 +273,11 @@ mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self,
194273
}
195274
while (received == 0 &&
196275
status >= 0 &&
197-
(self->timeout_ms == 0 || supervisor_ticks_ms64() - start_ticks <= self->timeout_ms) &&
276+
!timed_out &&
198277
!mp_hal_is_interrupted()) {
278+
if (self->timeout_ms != (uint)-1) {
279+
timed_out = self->timeout_ms == 0 || supervisor_ticks_ms64() - start_ticks >= self->timeout_ms;
280+
}
199281
RUN_BACKGROUND_TASKS;
200282
size_t available = esp_tls_get_bytes_avail(self->tls);
201283
if (available == 0) {
@@ -219,11 +301,13 @@ mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self,
219301
}
220302
}
221303
}
304+
} else {
305+
// Socket does not have a valid descriptor of either type
306+
mp_raise_OSError(MP_EBADF);
222307
}
223308

224-
if (received == 0) {
225-
// socket closed
226-
mp_raise_OSError(0);
309+
if (timed_out) {
310+
mp_raise_OSError(ETIMEDOUT);
227311
}
228312
return received;
229313
}
@@ -270,19 +354,39 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t* se
270354

271355
struct sockaddr_in source_addr;
272356
socklen_t socklen = sizeof(source_addr);
273-
mp_printf(&mp_plat_print, "recvfrom_into\n");
274-
int bytes_received = lwip_recvfrom(self->num, buf, len - 1, 0, (struct sockaddr *)&source_addr, &socklen);
275-
mp_printf(&mp_plat_print, "received:%d\n",bytes_received);
276357

277-
memcpy((void *)ip, (void*)&source_addr.sin_addr.s_addr, sizeof(source_addr.sin_addr.s_addr));
278-
*port = source_addr.sin_port;
358+
// LWIP Socket
359+
uint64_t start_ticks = supervisor_ticks_ms64();
360+
int received = -1;
361+
bool timed_out = false;
362+
while (received == -1 &&
363+
!timed_out &&
364+
!mp_hal_is_interrupted()) {
365+
if (self->timeout_ms != (uint)-1) {
366+
timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms;
367+
}
368+
RUN_BACKGROUND_TASKS;
369+
received = lwip_recvfrom(self->num, buf, len - 1, 0, (struct sockaddr *)&source_addr, &socklen);
370+
371+
// In non-blocking mode, fail instead of looping
372+
if (received == -1 && self->timeout_ms == 0) {
373+
mp_raise_OSError(MP_EAGAIN);
374+
}
375+
}
376+
377+
if (!timed_out) {
378+
memcpy((void *)ip, (void*)&source_addr.sin_addr.s_addr, sizeof(source_addr.sin_addr.s_addr));
379+
*port = source_addr.sin_port;
380+
} else {
381+
mp_raise_OSError(ETIMEDOUT);
382+
}
279383

280-
if (bytes_received < 0) {
384+
if (received < 0) {
281385
mp_raise_BrokenPipeError();
282386
return 0;
283387
} else {
284-
buf[bytes_received] = 0; // Null-terminate whatever we received
285-
return bytes_received;
388+
buf[received] = 0; // Null-terminate whatever we received
389+
return received;
286390
}
287391
}
288392

ports/esp32s2/common-hal/socketpool/Socket.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,7 @@ typedef struct {
4747
mp_uint_t timeout_ms;
4848
} socketpool_socket_obj_t;
4949

50+
void socket_reset(void);
51+
bool register_open_socket(socketpool_socket_obj_t* self);
52+
5053
#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_SOCKETPOOL_SOCKET_H

ports/esp32s2/supervisor/port.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "common-hal/pwmio/PWMOut.h"
4747
#include "common-hal/touchio/TouchIn.h"
4848
#include "common-hal/watchdog/WatchDogTimer.h"
49+
#include "common-hal/socketpool/Socket.h"
4950
#include "common-hal/wifi/__init__.h"
5051
#include "supervisor/memory.h"
5152
#include "supervisor/shared/tick.h"
@@ -174,6 +175,10 @@ void reset_port(void) {
174175
#if CIRCUITPY_WIFI
175176
wifi_reset();
176177
#endif
178+
179+
#if CIRCUITPY_SOCKETPOOL
180+
socket_reset();
181+
#endif
177182
}
178183

179184
void reset_to_bootloader(void) {

shared-bindings/socketpool/Socket.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,7 @@ STATIC mp_obj_t socketpool_socket_accept(mp_obj_t self_in) {
115115
uint8_t ip[4];
116116
uint port;
117117

118-
int socknum = common_hal_socketpool_socket_accept(self, ip, &port);
119-
120-
socketpool_socket_obj_t *sock = m_new_obj_with_finaliser(socketpool_socket_obj_t);
121-
sock->base.type = &socketpool_socket_type;
122-
sock->num = socknum;
123-
sock->tls = NULL;
124-
sock->ssl_context = NULL;
125-
sock->pool = self->pool;
118+
socketpool_socket_obj_t * sock = common_hal_socketpool_socket_accept(self, ip, &port);
126119

127120
mp_obj_t tuple_contents[2];
128121
tuple_contents[0] = MP_OBJ_FROM_PTR(sock);

shared-bindings/socketpool/Socket.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t* self, mp_u
3535

3636
bool common_hal_socketpool_socket_bind(socketpool_socket_obj_t* self, const char* host, size_t hostlen, uint8_t port);
3737
bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t* self, int backlog);
38-
int common_hal_socketpool_socket_accept(socketpool_socket_obj_t* self, uint8_t* ip, uint *port);
38+
socketpool_socket_obj_t * common_hal_socketpool_socket_accept(socketpool_socket_obj_t* self, uint8_t* ip, uint *port);
3939

4040
bool common_hal_socketpool_socket_connect(socketpool_socket_obj_t* self, const char* host, size_t hostlen, mp_int_t port);
4141
mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len);

0 commit comments

Comments
 (0)