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,114 @@ 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
+ // to do store Network interface
486
+ pkt_info->ipi_ifindex = buf->p ->if_idx ;
487
+ default_interface->network_if_from_netif_id (buf->p ->if_idx );
488
+ }
489
+ #endif
490
+ u16_t recv = netbuf_copy (buf, data, (u16_t )size);
491
+ netbuf_delete (buf);
492
+
493
+ return recv;
494
+ }
495
+
496
+ nsapi_size_or_error_t LWIP::socket_sendmsg (nsapi_socket_t handle, const SocketAddress &address,
497
+ const void *data, nsapi_size_t size,
498
+ nsapi_msghdr_t *control, nsapi_size_t control_size)
499
+ {
500
+ struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
501
+ ip_addr_t ip_addr = {};
502
+
503
+ // Used for backup the bound address if the packet must be sent from a specific address,
504
+ ip_addr_t bound_addr = {};
505
+ ip_addr_t src_addr = {};
506
+
507
+ nsapi_pktinfo_t *pkt_info = nullptr ;
445
508
446
509
nsapi_addr_t addr = address.get_addr ();
447
510
if (!convert_mbed_addr_to_lwip (&ip_addr, &addr)) {
448
511
return NSAPI_ERROR_PARAMETER;
449
512
}
450
- struct netif *netif_ = netif_get_by_index (s->conn ->pcb .ip ->netif_idx );
513
+
514
+ // We try to extract the pktinfo from the header
515
+
516
+ if (control) {
517
+ MsgHeaderIterator it (control, control_size);
518
+ while (it.has_next ()) {
519
+ auto *hdr = it.next ();
520
+ if (hdr->level == NSAPI_SOCKET && hdr->type == NSAPI_PKTINFO) {
521
+ pkt_info = reinterpret_cast <nsapi_pktinfo_t *>(hdr);
522
+ break ;
523
+ }
524
+ }
525
+ }
526
+
527
+ if (pkt_info) {
528
+ if (!convert_mbed_addr_to_lwip (&src_addr, &pkt_info->ipi_addr )) {
529
+ return NSAPI_ERROR_PARAMETER;
530
+ }
531
+ }
532
+
533
+ struct netif *netif_ = nullptr ;
534
+
535
+ if (pkt_info) {
536
+ // to do replace NULL with NetworkInterface
537
+ int index = default_interface->netif_id_from_network_if (NULL );
538
+ netif_ = netif_get_by_index (index);
539
+ } else {
540
+ netif_ = netif_get_by_index (s->conn ->pcb .ip ->netif_idx );
541
+ }
451
542
if (!netif_) {
452
543
netif_ = &default_interface->netif ;
453
544
}
545
+
454
546
if (netif_) {
455
547
if ((addr.version == NSAPI_IPv4 && !get_ipv4_addr (netif_)) ||
456
548
(addr.version == NSAPI_IPv6 && !get_ipv6_addr (netif_) && !get_ipv6_link_local_addr (netif_))) {
457
549
return NSAPI_ERROR_PARAMETER;
458
550
}
459
551
}
552
+
460
553
struct netbuf *buf = netbuf_new ();
461
554
462
555
err_t err = netbuf_ref (buf, data, (u16_t )size);
@@ -465,36 +558,29 @@ nsapi_size_or_error_t LWIP::socket_sendto(nsapi_socket_t handle, const SocketAdd
465
558
return err_remap (err);
466
559
}
467
560
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);
561
+ // handle src destination if required
562
+ if (pkt_info) {
563
+ // Backup the bound address
564
+ ip_addr_copy (bound_addr, s->conn ->pcb .udp ->local_ip );
565
+ // replace it with the source address
566
+ if (!ip_addr_isany (&src_addr)) {
567
+ ip_addr_copy (s->conn ->pcb .udp ->local_ip , src_addr);
568
+ }
472
569
}
473
570
474
- return size;
475
- }
571
+ err = netconn_sendto (s->conn , buf, &ip_addr, address.get_port ());
476
572
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;
573
+ if (pkt_info) {
574
+ // restore bound address
575
+ ip_addr_copy (s-> conn -> pcb . udp -> local_ip , bound_addr) ;
576
+ }
481
577
482
- err_t err = netconn_recv (s-> conn , & buf);
578
+ netbuf_delete ( buf);
483
579
if (err != ERR_OK) {
484
580
return err_remap (err);
485
581
}
486
582
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;
583
+ return size;
498
584
}
499
585
500
586
int32_t LWIP::find_multicast_member (const struct mbed_lwip_socket *s, const nsapi_ip_mreq_t *imr)
@@ -687,6 +773,19 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co
687
773
}
688
774
s->conn ->pcb .ip ->tos = (u8_t )(*(const int *)optval);
689
775
return 0 ;
776
+
777
+ case NSAPI_PKTINFO:
778
+ #if LWIP_NETBUF_RECVINFO
779
+ if (optlen != sizeof (int )) {
780
+ return NSAPI_ERROR_UNSUPPORTED;
781
+ }
782
+ if (*(const int *)optval) {
783
+ s->conn ->flags |= NETCONN_FLAG_PKTINFO;
784
+ } else {
785
+ s->conn ->flags &= ~NETCONN_FLAG_PKTINFO;
786
+ }
787
+ return 0 ;
788
+ #endif
690
789
default :
691
790
return NSAPI_ERROR_UNSUPPORTED;
692
791
}
0 commit comments