@@ -286,6 +286,15 @@ static const int error_lookup_table[] = {
286
286
#define MOD_NETWORK_SOCK_DGRAM (2)
287
287
#define MOD_NETWORK_SOCK_RAW (3)
288
288
289
+ // Total queue length for buffered UDP/raw incoming packets.
290
+ #define LWIP_INCOMING_PACKET_QUEUE_LEN (4)
291
+
292
+ typedef struct _lwip_incoming_packet_t {
293
+ struct pbuf * pbuf ;
294
+ ip_addr_t peer_addr ;
295
+ uint16_t peer_port ;
296
+ } lwip_incoming_packet_t ;
297
+
289
298
typedef struct _lwip_socket_obj_t {
290
299
mp_obj_base_t base ;
291
300
@@ -294,8 +303,11 @@ typedef struct _lwip_socket_obj_t {
294
303
struct udp_pcb * udp ;
295
304
struct raw_pcb * raw ;
296
305
} pcb ;
306
+
307
+ // Data structure that holds incoming pbuf's.
308
+ // Each socket type has different state that it needs to keep track of.
297
309
volatile union {
298
- struct pbuf * pbuf ;
310
+ // TCP listening sockets have a queue of incoming connections, implemented as a ringbuffer.
299
311
struct {
300
312
uint8_t alloc ;
301
313
uint8_t iget ;
@@ -305,10 +317,23 @@ typedef struct _lwip_socket_obj_t {
305
317
struct tcp_pcb * * array ; // if alloc != 0
306
318
} tcp ;
307
319
} connection ;
320
+
321
+ // Connected TCP sockets have a single incoming pbuf that new data is appended to.
322
+ struct {
323
+ struct pbuf * pbuf ;
324
+ } tcp ;
325
+
326
+ // UDP and raw sockets have a queue of incoming pbuf's, implemented as a ringbuffer.
327
+ struct {
328
+ uint8_t iget ; // ringbuffer read index
329
+ uint8_t iput ; // ringbuffer write index
330
+ lwip_incoming_packet_t * array ;
331
+ } udp_raw ;
308
332
} incoming ;
333
+
309
334
mp_obj_t callback ;
310
- ip_addr_t peer ;
311
- mp_uint_t peer_port ;
335
+ ip_addr_t tcp_peer_addr ;
336
+ mp_uint_t tcp_peer_port ;
312
337
mp_uint_t timeout ;
313
338
uint16_t recv_offset ;
314
339
@@ -347,9 +372,21 @@ static void lwip_socket_free_incoming(lwip_socket_obj_t *socket) {
347
372
&& socket -> pcb .tcp -> state == LISTEN ;
348
373
349
374
if (!socket_is_listener ) {
350
- if (socket -> incoming .pbuf != NULL ) {
351
- pbuf_free (socket -> incoming .pbuf );
352
- socket -> incoming .pbuf = NULL ;
375
+ if (socket -> type == MOD_NETWORK_SOCK_STREAM ) {
376
+ if (socket -> incoming .tcp .pbuf != NULL ) {
377
+ pbuf_free (socket -> incoming .tcp .pbuf );
378
+ socket -> incoming .tcp .pbuf = NULL ;
379
+ }
380
+ } else {
381
+ for (size_t i = 0 ; i < LWIP_INCOMING_PACKET_QUEUE_LEN ; ++ i ) {
382
+ lwip_incoming_packet_t * slot = & socket -> incoming .udp_raw .array [i ];
383
+ if (slot -> pbuf != NULL ) {
384
+ pbuf_free (slot -> pbuf );
385
+ slot -> pbuf = NULL ;
386
+ }
387
+ }
388
+ socket -> incoming .udp_raw .iget = 0 ;
389
+ socket -> incoming .udp_raw .iput = 0 ;
353
390
}
354
391
} else {
355
392
uint8_t alloc = socket -> incoming .connection .alloc ;
@@ -407,6 +444,19 @@ static inline void exec_user_callback(lwip_socket_obj_t *socket) {
407
444
}
408
445
}
409
446
447
+ static void udp_raw_incoming (lwip_socket_obj_t * socket , struct pbuf * p , const ip_addr_t * addr , u16_t port ) {
448
+ lwip_incoming_packet_t * slot = & socket -> incoming .udp_raw .array [socket -> incoming .udp_raw .iput ];
449
+ if (slot -> pbuf != NULL ) {
450
+ // No room in the inn, drop the packet.
451
+ pbuf_free (p );
452
+ } else {
453
+ slot -> pbuf = p ;
454
+ slot -> peer_addr = * addr ;
455
+ slot -> peer_port = port ;
456
+ socket -> incoming .udp_raw .iput = (socket -> incoming .udp_raw .iput + 1 ) % LWIP_INCOMING_PACKET_QUEUE_LEN ;
457
+ }
458
+ }
459
+
410
460
#if MICROPY_PY_LWIP_SOCK_RAW
411
461
// Callback for incoming raw packets.
412
462
#if LWIP_VERSION_MAJOR < 2
@@ -416,13 +466,7 @@ static u8_t _lwip_raw_incoming(void *arg, struct raw_pcb *pcb, struct pbuf *p, c
416
466
#endif
417
467
{
418
468
lwip_socket_obj_t * socket = (lwip_socket_obj_t * )arg ;
419
-
420
- if (socket -> incoming .pbuf != NULL ) {
421
- pbuf_free (p );
422
- } else {
423
- socket -> incoming .pbuf = p ;
424
- memcpy (& socket -> peer , addr , sizeof (socket -> peer ));
425
- }
469
+ udp_raw_incoming (socket , p , addr , 0 );
426
470
return 1 ; // we ate the packet
427
471
}
428
472
#endif
@@ -436,15 +480,7 @@ static void _lwip_udp_incoming(void *arg, struct udp_pcb *upcb, struct pbuf *p,
436
480
#endif
437
481
{
438
482
lwip_socket_obj_t * socket = (lwip_socket_obj_t * )arg ;
439
-
440
- if (socket -> incoming .pbuf != NULL ) {
441
- // That's why they call it "unreliable". No room in the inn, drop the packet.
442
- pbuf_free (p );
443
- } else {
444
- socket -> incoming .pbuf = p ;
445
- socket -> peer_port = (mp_uint_t )port ;
446
- memcpy (& socket -> peer , addr , sizeof (socket -> peer ));
447
- }
483
+ udp_raw_incoming (socket , p , addr , port );
448
484
}
449
485
450
486
// Callback for general tcp errors.
@@ -562,13 +598,13 @@ static err_t _lwip_tcp_recv(void *arg, struct tcp_pcb *tcpb, struct pbuf *p, err
562
598
return ERR_OK ;
563
599
}
564
600
565
- if (socket -> incoming .pbuf == NULL ) {
566
- socket -> incoming .pbuf = p ;
601
+ if (socket -> incoming .tcp . pbuf == NULL ) {
602
+ socket -> incoming .tcp . pbuf = p ;
567
603
} else {
568
604
#ifdef SOCKET_SINGLE_PBUF
569
605
return ERR_BUF ;
570
606
#else
571
- pbuf_cat (socket -> incoming .pbuf , p );
607
+ pbuf_cat (socket -> incoming .tcp . pbuf , p );
572
608
#endif
573
609
}
574
610
@@ -639,7 +675,9 @@ static mp_uint_t lwip_raw_udp_send(lwip_socket_obj_t *socket, const byte *buf, m
639
675
// Helper function for recv/recvfrom to handle raw/UDP packets
640
676
static mp_uint_t lwip_raw_udp_receive (lwip_socket_obj_t * socket , byte * buf , mp_uint_t len , ip_addr_t * ip , mp_uint_t * port , int * _errno ) {
641
677
642
- if (socket -> incoming .pbuf == NULL ) {
678
+ lwip_incoming_packet_t * slot = & socket -> incoming .udp_raw .array [socket -> incoming .udp_raw .iget ];
679
+
680
+ if (slot -> pbuf == NULL ) {
643
681
if (socket -> timeout == 0 ) {
644
682
// Non-blocking socket.
645
683
* _errno = MP_EAGAIN ;
@@ -648,7 +686,7 @@ static mp_uint_t lwip_raw_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_u
648
686
649
687
// Wait for data to arrive on UDP socket.
650
688
mp_uint_t start = mp_hal_ticks_ms ();
651
- while (socket -> incoming . pbuf == NULL ) {
689
+ while (slot -> pbuf == NULL ) {
652
690
if (socket -> timeout != -1 && mp_hal_ticks_ms () - start > socket -> timeout ) {
653
691
* _errno = MP_ETIMEDOUT ;
654
692
return -1 ;
@@ -658,17 +696,18 @@ static mp_uint_t lwip_raw_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_u
658
696
}
659
697
660
698
if (ip != NULL ) {
661
- memcpy ( ip , & socket -> peer , sizeof ( socket -> peer )) ;
662
- * port = socket -> peer_port ;
699
+ * ip = slot -> peer_addr ;
700
+ * port = slot -> peer_port ;
663
701
}
664
702
665
- struct pbuf * p = socket -> incoming . pbuf ;
703
+ struct pbuf * p = slot -> pbuf ;
666
704
667
705
MICROPY_PY_LWIP_ENTER
668
706
669
707
u16_t result = pbuf_copy_partial (p , buf , ((p -> tot_len > len ) ? len : p -> tot_len ), 0 );
670
708
pbuf_free (p );
671
- socket -> incoming .pbuf = NULL ;
709
+ slot -> pbuf = NULL ;
710
+ socket -> incoming .udp_raw .iget = (socket -> incoming .udp_raw .iget + 1 ) % LWIP_INCOMING_PACKET_QUEUE_LEN ;
672
711
673
712
MICROPY_PY_LWIP_EXIT
674
713
@@ -780,7 +819,7 @@ static mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
780
819
// Check for any pending errors
781
820
STREAM_ERROR_CHECK (socket );
782
821
783
- if (socket -> incoming .pbuf == NULL ) {
822
+ if (socket -> incoming .tcp . pbuf == NULL ) {
784
823
785
824
// Non-blocking socket
786
825
if (socket -> timeout == 0 ) {
@@ -792,7 +831,7 @@ static mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
792
831
}
793
832
794
833
mp_uint_t start = mp_hal_ticks_ms ();
795
- while (socket -> state == STATE_CONNECTED && socket -> incoming .pbuf == NULL ) {
834
+ while (socket -> state == STATE_CONNECTED && socket -> incoming .tcp . pbuf == NULL ) {
796
835
if (socket -> timeout != -1 && mp_hal_ticks_ms () - start > socket -> timeout ) {
797
836
* _errno = MP_ETIMEDOUT ;
798
837
return -1 ;
@@ -801,7 +840,7 @@ static mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
801
840
}
802
841
803
842
if (socket -> state == STATE_PEER_CLOSED ) {
804
- if (socket -> incoming .pbuf == NULL ) {
843
+ if (socket -> incoming .tcp . pbuf == NULL ) {
805
844
// socket closed and no data left in buffer
806
845
return 0 ;
807
846
}
@@ -819,7 +858,7 @@ static mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
819
858
820
859
assert (socket -> pcb .tcp != NULL);
821
860
822
- struct pbuf * p = socket -> incoming .pbuf ;
861
+ struct pbuf * p = socket -> incoming .tcp . pbuf ;
823
862
824
863
mp_uint_t remaining = p -> len - socket -> recv_offset ;
825
864
if (len > remaining ) {
@@ -830,7 +869,7 @@ static mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
830
869
831
870
remaining -= len ;
832
871
if (remaining == 0 ) {
833
- socket -> incoming .pbuf = p -> next ;
872
+ socket -> incoming .tcp . pbuf = p -> next ;
834
873
// If we don't ref here, free() will free the entire chain,
835
874
// if we ref, it does what we need: frees 1st buf, and decrements
836
875
// next buf's refcount back to 1.
@@ -854,8 +893,18 @@ static const mp_obj_type_t lwip_socket_type;
854
893
855
894
static void lwip_socket_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
856
895
lwip_socket_obj_t * self = MP_OBJ_TO_PTR (self_in );
857
- mp_printf (print , "<socket state=%d timeout=%d incoming=%p off=%d>" , self -> state , self -> timeout ,
858
- self -> incoming .pbuf , self -> recv_offset );
896
+ mp_printf (print , "<socket state=%d timeout=%d incoming=" , self -> state , self -> timeout );
897
+ if (self -> type == MOD_NETWORK_SOCK_STREAM ) {
898
+ mp_printf (print , "%p off=%d>" , self -> incoming .tcp .pbuf , self -> recv_offset );
899
+ } else {
900
+ int num_in_queue = 0 ;
901
+ for (size_t i = 0 ; i < LWIP_INCOMING_PACKET_QUEUE_LEN ; ++ i ) {
902
+ if (self -> incoming .udp_raw .array [i ].pbuf != NULL ) {
903
+ ++ num_in_queue ;
904
+ }
905
+ }
906
+ mp_printf (print , "%d>" , num_in_queue );
907
+ }
859
908
}
860
909
861
910
// FIXME: Only supports two arguments at present
@@ -884,16 +933,22 @@ static mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, size_t n_args, s
884
933
socket -> incoming .connection .tcp .item = NULL ;
885
934
break ;
886
935
case MOD_NETWORK_SOCK_DGRAM :
887
- socket -> pcb .udp = udp_new ();
888
- socket -> incoming .pbuf = NULL ;
889
- break ;
890
936
#if MICROPY_PY_LWIP_SOCK_RAW
891
- case MOD_NETWORK_SOCK_RAW : {
892
- mp_int_t proto = n_args <= 2 ? 0 : mp_obj_get_int (args [2 ]);
893
- socket -> pcb .raw = raw_new (proto );
894
- break ;
895
- }
937
+ case MOD_NETWORK_SOCK_RAW :
896
938
#endif
939
+ if (socket -> type == MOD_NETWORK_SOCK_DGRAM ) {
940
+ socket -> pcb .udp = udp_new ();
941
+ }
942
+ #if MICROPY_PY_LWIP_SOCK_RAW
943
+ else {
944
+ mp_int_t proto = n_args <= 2 ? 0 : mp_obj_get_int (args [2 ]);
945
+ socket -> pcb .raw = raw_new (proto );
946
+ }
947
+ #endif
948
+ socket -> incoming .udp_raw .iget = 0 ;
949
+ socket -> incoming .udp_raw .iput = 0 ;
950
+ socket -> incoming .udp_raw .array = m_new0 (lwip_incoming_packet_t , LWIP_INCOMING_PACKET_QUEUE_LEN );
951
+ break ;
897
952
default :
898
953
mp_raise_OSError (MP_EINVAL );
899
954
}
@@ -1075,7 +1130,7 @@ static mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
1075
1130
// ...and set up the new socket for it.
1076
1131
socket2 -> domain = MOD_NETWORK_AF_INET ;
1077
1132
socket2 -> type = MOD_NETWORK_SOCK_STREAM ;
1078
- socket2 -> incoming .pbuf = NULL ;
1133
+ socket2 -> incoming .tcp . pbuf = NULL ;
1079
1134
socket2 -> timeout = socket -> timeout ;
1080
1135
socket2 -> state = STATE_CONNECTED ;
1081
1136
socket2 -> recv_offset = 0 ;
@@ -1130,8 +1185,8 @@ static mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
1130
1185
socket -> state = STATE_NEW ;
1131
1186
mp_raise_OSError (error_lookup_table [- err ]);
1132
1187
}
1133
- socket -> peer_port = ( mp_uint_t ) port ;
1134
- memcpy ( & socket -> peer , & dest , sizeof ( socket -> peer )) ;
1188
+ socket -> tcp_peer_addr = dest ;
1189
+ socket -> tcp_peer_port = ( mp_uint_t ) port ;
1135
1190
MICROPY_PY_LWIP_EXIT
1136
1191
1137
1192
// And now we wait...
@@ -1299,8 +1354,8 @@ static mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
1299
1354
mp_uint_t ret = 0 ;
1300
1355
switch (socket -> type ) {
1301
1356
case MOD_NETWORK_SOCK_STREAM : {
1302
- memcpy ( & ip , & socket -> peer , sizeof ( socket -> peer )) ;
1303
- port = (mp_uint_t )socket -> peer_port ;
1357
+ ip = socket -> tcp_peer_addr ;
1358
+ port = (mp_uint_t )socket -> tcp_peer_port ;
1304
1359
ret = lwip_tcp_receive (socket , (byte * )vstr .buf , len , & _errno );
1305
1360
break ;
1306
1361
}
@@ -1537,9 +1592,15 @@ static mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_
1537
1592
if (lwip_socket_incoming_array (socket )[socket -> incoming .connection .iget ] != NULL ) {
1538
1593
ret |= MP_STREAM_POLL_RD ;
1539
1594
}
1595
+ } else if (socket -> type == MOD_NETWORK_SOCK_STREAM ) {
1596
+ // For TCP sockets there is just one slot for incoming data
1597
+ if (socket -> incoming .tcp .pbuf != NULL ) {
1598
+ ret |= MP_STREAM_POLL_RD ;
1599
+ }
1540
1600
} else {
1541
- // Otherwise there is just one slot for incoming data
1542
- if (socket -> incoming .pbuf != NULL ) {
1601
+ // Otherwise for UDP/raw there is a queue of incoming data
1602
+ lwip_incoming_packet_t * slot = & socket -> incoming .udp_raw .array [socket -> incoming .udp_raw .iget ];
1603
+ if (slot -> pbuf != NULL ) {
1543
1604
ret |= MP_STREAM_POLL_RD ;
1544
1605
}
1545
1606
}
0 commit comments