59
59
#define MDNS_QUERY_TIMEOUT_MS (5000)
60
60
#define MDNS_LOCAL_SUFFIX ".local"
61
61
62
+ enum {
63
+ SOCKET_STATE_NEW ,
64
+ SOCKET_STATE_CONNECTED ,
65
+ SOCKET_STATE_PEER_CLOSED ,
66
+ };
67
+
62
68
typedef struct _socket_obj_t {
63
69
mp_obj_base_t base ;
64
70
int fd ;
65
71
uint8_t domain ;
66
72
uint8_t type ;
67
73
uint8_t proto ;
68
- bool peer_closed ;
74
+ uint8_t state ;
69
75
unsigned int retries ;
70
76
#if MICROPY_PY_USOCKET_EVENTS
71
77
mp_obj_t events_callback ;
@@ -254,7 +260,6 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, siz
254
260
sock -> domain = AF_INET ;
255
261
sock -> type = SOCK_STREAM ;
256
262
sock -> proto = 0 ;
257
- sock -> peer_closed = false;
258
263
if (n_args > 0 ) {
259
264
sock -> domain = mp_obj_get_int (args [0 ]);
260
265
if (n_args > 1 ) {
@@ -265,6 +270,8 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, siz
265
270
}
266
271
}
267
272
273
+ sock -> state = sock -> type == SOCK_STREAM ? SOCKET_STATE_NEW : SOCKET_STATE_CONNECTED ;
274
+
268
275
sock -> fd = lwip_socket (sock -> domain , sock -> type , sock -> proto );
269
276
if (sock -> fd < 0 ) {
270
277
mp_raise_OSError (errno );
@@ -278,6 +285,7 @@ STATIC mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) {
278
285
socket_obj_t * self = MP_OBJ_TO_PTR (arg0 );
279
286
struct addrinfo * res ;
280
287
_socket_getaddrinfo (arg1 , & res );
288
+ self -> state = SOCKET_STATE_CONNECTED ;
281
289
int r = lwip_bind (self -> fd , res -> ai_addr , res -> ai_addrlen );
282
290
lwip_freeaddrinfo (res );
283
291
if (r < 0 ) {
@@ -290,6 +298,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
290
298
STATIC mp_obj_t socket_listen (const mp_obj_t arg0 , const mp_obj_t arg1 ) {
291
299
socket_obj_t * self = MP_OBJ_TO_PTR (arg0 );
292
300
int backlog = mp_obj_get_int (arg1 );
301
+ self -> state = SOCKET_STATE_CONNECTED ;
293
302
int r = lwip_listen (self -> fd , backlog );
294
303
if (r < 0 ) {
295
304
mp_raise_OSError (errno );
@@ -332,7 +341,7 @@ STATIC mp_obj_t socket_accept(const mp_obj_t arg0) {
332
341
sock -> domain = self -> domain ;
333
342
sock -> type = self -> type ;
334
343
sock -> proto = self -> proto ;
335
- sock -> peer_closed = false ;
344
+ sock -> state = SOCKET_STATE_CONNECTED ;
336
345
_socket_settimeout (sock , UINT64_MAX );
337
346
338
347
// make the return value
@@ -351,6 +360,7 @@ STATIC mp_obj_t socket_connect(const mp_obj_t arg0, const mp_obj_t arg1) {
351
360
struct addrinfo * res ;
352
361
_socket_getaddrinfo (arg1 , & res );
353
362
MP_THREAD_GIL_EXIT ();
363
+ self -> state = SOCKET_STATE_CONNECTED ;
354
364
int r = lwip_connect (self -> fd , res -> ai_addr , res -> ai_addrlen );
355
365
MP_THREAD_GIL_ENTER ();
356
366
lwip_freeaddrinfo (res );
@@ -471,11 +481,17 @@ STATIC mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size,
471
481
struct sockaddr * from , socklen_t * from_len , int * errcode ) {
472
482
socket_obj_t * sock = MP_OBJ_TO_PTR (self_in );
473
483
484
+ // A new socket cannot be read from.
485
+ if (sock -> state == SOCKET_STATE_NEW ) {
486
+ * errcode = MP_ENOTCONN ;
487
+ return MP_STREAM_ERROR ;
488
+ }
489
+
474
490
// If the peer closed the connection then the lwIP socket API will only return "0" once
475
491
// from lwip_recvfrom and then block on subsequent calls. To emulate POSIX behaviour,
476
492
// which continues to return "0" for each call on a closed socket, we set a flag when
477
493
// the peer closed the socket.
478
- if (sock -> peer_closed ) {
494
+ if (sock -> state == SOCKET_STATE_PEER_CLOSED ) {
479
495
return 0 ;
480
496
}
481
497
@@ -500,7 +516,7 @@ STATIC mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size,
500
516
MP_THREAD_GIL_ENTER ();
501
517
}
502
518
if (r == 0 ) {
503
- sock -> peer_closed = true ;
519
+ sock -> state = SOCKET_STATE_PEER_CLOSED ;
504
520
}
505
521
if (r >= 0 ) {
506
522
return r ;
@@ -702,6 +718,12 @@ STATIC mp_uint_t socket_stream_ioctl(mp_obj_t self_in, mp_uint_t request, uintpt
702
718
if (FD_ISSET (socket -> fd , & efds )) {
703
719
ret |= MP_STREAM_POLL_HUP ;
704
720
}
721
+
722
+ // New (unconnected) sockets are writable and have HUP set.
723
+ if (socket -> state == SOCKET_STATE_NEW ) {
724
+ ret |= (arg & MP_STREAM_POLL_WR ) | MP_STREAM_POLL_HUP ;
725
+ }
726
+
705
727
return ret ;
706
728
} else if (request == MP_STREAM_CLOSE ) {
707
729
if (socket -> fd >= 0 ) {
0 commit comments