15
15
* limitations under the License.
16
16
*/
17
17
#include " nsapi.h"
18
+ #include " netsocket/MsgHeader.h"
18
19
#include " mbed_interface.h"
19
20
#include " mbed_assert.h"
20
21
#include " Semaphore.h"
21
- #include < stdio.h>
22
22
#include < stdbool.h>
23
23
#include < string.h>
24
24
37
37
#include " lwip/raw.h"
38
38
#include " lwip/netif.h"
39
39
#include " lwip/lwip_errno.h"
40
+ #include " lwip/ip_addr.h"
40
41
#include " lwip-sys/arch/sys_arch.h"
41
42
42
43
#include " LWIPStack.h"
@@ -271,7 +272,9 @@ nsapi_error_t LWIP::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto)
271
272
arena_dealloc (s);
272
273
return NSAPI_ERROR_NO_SOCKET;
273
274
}
274
-
275
+ #if LWIP_NETBUF_RECVINFO
276
+ s->conn ->flags &= ~NETCONN_FLAG_PKTINFO;
277
+ #endif
275
278
netconn_set_nonblocking (s->conn , true );
276
279
*(struct mbed_lwip_socket **)handle = s;
277
280
return 0 ;
@@ -439,24 +442,111 @@ nsapi_size_or_error_t LWIP::socket_recv(nsapi_socket_t handle, void *data, nsapi
439
442
}
440
443
441
444
nsapi_size_or_error_t LWIP::socket_sendto (nsapi_socket_t handle, const SocketAddress &address, const void *data, nsapi_size_t size)
445
+ {
446
+ return socket_sendmsg (handle, address, data, size, NULL , 0 );
447
+ }
448
+
449
+ nsapi_size_or_error_t LWIP::socket_recvfrom (nsapi_socket_t handle, SocketAddress *address, void *data, nsapi_size_t size)
450
+ {
451
+ return socket_recvmsg (handle, address, data, size, NULL , 0 );
452
+
453
+ }
454
+
455
+ nsapi_size_or_error_t LWIP::socket_recvmsg (nsapi_socket_t handle, SocketAddress *address,
456
+ void *data, nsapi_size_t size,
457
+ nsapi_msghdr_t *control, nsapi_size_t control_size)
442
458
{
443
459
struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
444
- ip_addr_t ip_addr;
460
+ struct netbuf *buf;
461
+
462
+ err_t err = netconn_recv (s->conn , &buf);
463
+ if (err != ERR_OK) {
464
+ return err_remap (err);
465
+ }
466
+
467
+ if (address) {
468
+ nsapi_addr_t addr;
469
+ convert_lwip_addr_to_mbed (&addr, netbuf_fromaddr (buf));
470
+ address->set_addr (addr);
471
+ address->set_port (netbuf_fromport (buf));
472
+ }
473
+ #if LWIP_NETBUF_RECVINFO
474
+ if ((s->conn ->flags & NETCONN_FLAG_PKTINFO) && control && control_size >= sizeof (nsapi_pktinfo_t )) {
475
+ nsapi_pktinfo_t *pkt_info = reinterpret_cast <nsapi_pktinfo *>(control);
476
+ memset (control, 0 , control_size);
477
+ // Not optimal but sufficient. It should help the caller in not iterating over
478
+ // the control data structure
479
+ control->len = control_size;
480
+ control->level = NSAPI_SOCKET;
481
+ control->type = NSAPI_PKTINFO;
482
+ // retrieve the destination
483
+ convert_lwip_addr_to_mbed (&pkt_info->ipi_addr , netbuf_destaddr (buf));
484
+ // retrieve the interface id
485
+ pkt_info->network_interface = default_interface->network_if_from_netif_id (buf->p ->if_idx );
486
+ }
487
+ #endif
488
+ u16_t recv = netbuf_copy (buf, data, (u16_t )size);
489
+ netbuf_delete (buf);
490
+
491
+ return recv;
492
+ }
493
+
494
+ nsapi_size_or_error_t LWIP::socket_sendmsg (nsapi_socket_t handle, const SocketAddress &address,
495
+ const void *data, nsapi_size_t size,
496
+ nsapi_msghdr_t *control, nsapi_size_t control_size)
497
+ {
498
+ struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
499
+ ip_addr_t ip_addr = {};
500
+
501
+ // Used for backup the bound address if the packet must be sent from a specific address,
502
+ ip_addr_t bound_addr = {};
503
+ ip_addr_t src_addr = {};
504
+
505
+ nsapi_pktinfo_t *pkt_info = nullptr ;
445
506
446
507
nsapi_addr_t addr = address.get_addr ();
447
508
if (!convert_mbed_addr_to_lwip (&ip_addr, &addr)) {
448
509
return NSAPI_ERROR_PARAMETER;
449
510
}
450
- struct netif *netif_ = netif_get_by_index (s->conn ->pcb .ip ->netif_idx );
511
+
512
+ // We try to extract the pktinfo from the header
513
+
514
+ if (control) {
515
+ MsgHeaderIterator it (control, control_size);
516
+ while (it.has_next ()) {
517
+ auto *hdr = it.next ();
518
+ if (hdr->level == NSAPI_SOCKET && hdr->type == NSAPI_PKTINFO) {
519
+ pkt_info = reinterpret_cast <nsapi_pktinfo_t *>(hdr);
520
+ break ;
521
+ }
522
+ }
523
+ }
524
+
525
+ if (pkt_info) {
526
+ if (!convert_mbed_addr_to_lwip (&src_addr, &pkt_info->ipi_addr )) {
527
+ return NSAPI_ERROR_PARAMETER;
528
+ }
529
+ }
530
+
531
+ struct netif *netif_ = nullptr ;
532
+
533
+ if (pkt_info) {
534
+ int index = default_interface->netif_id_from_network_if ((NetworkInterface *)pkt_info->network_interface );
535
+ netif_ = netif_get_by_index (index );
536
+ } else {
537
+ netif_ = netif_get_by_index (s->conn ->pcb .ip ->netif_idx );
538
+ }
451
539
if (!netif_) {
452
540
netif_ = &default_interface->netif ;
453
541
}
542
+
454
543
if (netif_) {
455
544
if ((addr.version == NSAPI_IPv4 && !get_ipv4_addr (netif_)) ||
456
545
(addr.version == NSAPI_IPv6 && !get_ipv6_addr (netif_) && !get_ipv6_link_local_addr (netif_))) {
457
546
return NSAPI_ERROR_PARAMETER;
458
547
}
459
548
}
549
+
460
550
struct netbuf *buf = netbuf_new ();
461
551
462
552
err_t err = netbuf_ref (buf, data, (u16_t )size);
@@ -465,36 +555,29 @@ nsapi_size_or_error_t LWIP::socket_sendto(nsapi_socket_t handle, const SocketAdd
465
555
return err_remap (err);
466
556
}
467
557
468
- err = netconn_sendto (s->conn , buf, &ip_addr, address.get_port ());
469
- netbuf_delete (buf);
470
- if (err != ERR_OK) {
471
- return err_remap (err);
558
+ // handle src destination if required
559
+ if (pkt_info) {
560
+ // Backup the bound address
561
+ ip_addr_copy (bound_addr, s->conn ->pcb .udp ->local_ip );
562
+ // replace it with the source address
563
+ if (!ip_addr_isany (&src_addr)) {
564
+ ip_addr_copy (s->conn ->pcb .udp ->local_ip , src_addr);
565
+ }
472
566
}
473
567
474
- return size;
475
- }
568
+ err = netconn_sendto (s->conn , buf, &ip_addr, address.get_port ());
476
569
477
- nsapi_size_or_error_t LWIP::socket_recvfrom ( nsapi_socket_t handle, SocketAddress *address, void *data, nsapi_size_t size)
478
- {
479
- struct mbed_lwip_socket *s = ( struct mbed_lwip_socket *)handle ;
480
- struct netbuf *buf;
570
+ if (pkt_info) {
571
+ // restore bound address
572
+ ip_addr_copy (s-> conn -> pcb . udp -> local_ip , bound_addr) ;
573
+ }
481
574
482
- err_t err = netconn_recv (s-> conn , & buf);
575
+ netbuf_delete ( buf);
483
576
if (err != ERR_OK) {
484
577
return err_remap (err);
485
578
}
486
579
487
- if (address) {
488
- nsapi_addr_t addr;
489
- convert_lwip_addr_to_mbed (&addr, netbuf_fromaddr (buf));
490
- address->set_addr (addr);
491
- address->set_port (netbuf_fromport (buf));
492
- }
493
-
494
- u16_t recv = netbuf_copy (buf, data, (u16_t )size);
495
- netbuf_delete (buf);
496
-
497
- return recv;
580
+ return size;
498
581
}
499
582
500
583
int32_t LWIP::find_multicast_member (const struct mbed_lwip_socket *s, const nsapi_ip_mreq_t *imr)
@@ -687,6 +770,19 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co
687
770
}
688
771
s->conn ->pcb .ip ->tos = (u8_t )(*(const int *)optval);
689
772
return 0 ;
773
+
774
+ case NSAPI_PKTINFO:
775
+ #if LWIP_NETBUF_RECVINFO
776
+ if (optlen != sizeof (int )) {
777
+ return NSAPI_ERROR_UNSUPPORTED;
778
+ }
779
+ if (*(const int *)optval) {
780
+ s->conn ->flags |= NETCONN_FLAG_PKTINFO;
781
+ } else {
782
+ s->conn ->flags &= ~NETCONN_FLAG_PKTINFO;
783
+ }
784
+ return 0 ;
785
+ #endif
690
786
default :
691
787
return NSAPI_ERROR_UNSUPPORTED;
692
788
}
0 commit comments