38
38
#include "components/lwip/lwip/src/include/lwip/sys.h"
39
39
#include "components/lwip/lwip/src/include/lwip/netdb.h"
40
40
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
+
41
67
STATIC void _lazy_init_LWIP (socketpool_socket_obj_t * self ) {
42
68
if (self -> num != -1 ) {
43
69
return ; //safe to call on existing socket
@@ -47,7 +73,7 @@ STATIC void _lazy_init_LWIP(socketpool_socket_obj_t* self) {
47
73
}
48
74
int socknum = -1 ;
49
75
socknum = lwip_socket (self -> family , self -> type , self -> ipproto );
50
- if (socknum < 0 ) {
76
+ if (socknum < 0 || ! register_open_socket ( self ) ) {
51
77
mp_raise_RuntimeError (translate ("Out of sockets" ));
52
78
}
53
79
self -> num = socknum ;
@@ -78,34 +104,74 @@ bool common_hal_socketpool_socket_bind(socketpool_socket_obj_t* self,
78
104
bind_addr .sin_family = AF_INET ;
79
105
bind_addr .sin_port = htons (port );
80
106
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 ;
82
114
}
83
115
84
116
bool common_hal_socketpool_socket_listen (socketpool_socket_obj_t * self , int backlog ) {
85
117
return lwip_listen (self -> num , backlog ) == 0 ;
86
118
}
87
119
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 ,
89
121
uint8_t * ip , uint * port ) {
90
122
struct sockaddr_in accept_addr ;
91
123
socklen_t socklen = sizeof (accept_addr );
92
-
93
124
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
+ }
96
141
RUN_BACKGROUND_TASKS ;
97
142
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
+ }
98
147
}
99
- mp_printf (& mp_plat_print , "oldsoc:%d newsoc:%d\n" ,self -> num , newsoc );
100
148
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
+ }
103
156
104
157
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
+
105
170
lwip_fcntl (newsoc , F_SETFL , O_NONBLOCK );
106
- return newsoc ;
171
+ return sock ;
107
172
} else {
108
- return 0 ;
173
+ mp_raise_OSError (MP_EBADF );
174
+ return NULL ;
109
175
}
110
176
}
111
177
@@ -158,9 +224,10 @@ bool common_hal_socketpool_socket_get_connected(socketpool_socket_obj_t* self) {
158
224
}
159
225
160
226
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 ;
162
228
if (self -> num != -1 ) {
163
229
// LWIP Socket
230
+ // TODO: deal with potential failure/add timeout?
164
231
sent = lwip_send (self -> num , buf , len , 0 );
165
232
} else if (self -> tls != NULL ) {
166
233
// TLS Socket
@@ -174,15 +241,27 @@ mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const
174
241
}
175
242
176
243
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;
178
246
179
247
if (self -> num != -1 ) {
180
248
// 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 );
185
259
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
+ }
186
265
} else if (self -> tls != NULL ) {
187
266
// TLS Socket
188
267
int status = 0 ;
@@ -194,8 +273,11 @@ mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self,
194
273
}
195
274
while (received == 0 &&
196
275
status >= 0 &&
197
- ( self -> timeout_ms == 0 || supervisor_ticks_ms64 () - start_ticks <= self -> timeout_ms ) &&
276
+ ! timed_out &&
198
277
!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
+ }
199
281
RUN_BACKGROUND_TASKS ;
200
282
size_t available = esp_tls_get_bytes_avail (self -> tls );
201
283
if (available == 0 ) {
@@ -219,11 +301,13 @@ mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self,
219
301
}
220
302
}
221
303
}
304
+ } else {
305
+ // Socket does not have a valid descriptor of either type
306
+ mp_raise_OSError (MP_EBADF );
222
307
}
223
308
224
- if (received == 0 ) {
225
- // socket closed
226
- mp_raise_OSError (0 );
309
+ if (timed_out ) {
310
+ mp_raise_OSError (ETIMEDOUT );
227
311
}
228
312
return received ;
229
313
}
@@ -270,19 +354,39 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t* se
270
354
271
355
struct sockaddr_in source_addr ;
272
356
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 );
276
357
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
+ }
279
383
280
- if (bytes_received < 0 ) {
384
+ if (received < 0 ) {
281
385
mp_raise_BrokenPipeError ();
282
386
return 0 ;
283
387
} 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 ;
286
390
}
287
391
}
288
392
0 commit comments