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"
@@ -439,24 +440,109 @@ nsapi_size_or_error_t LWIP::socket_recv(nsapi_socket_t handle, void *data, nsapi
439
440
}
440
441
441
442
nsapi_size_or_error_t LWIP::socket_sendto (nsapi_socket_t handle, const SocketAddress &address, const void *data, nsapi_size_t size)
443
+ {
444
+ return socket_sendmsg (handle, address, data, size, NULL , 0 );
445
+ }
446
+
447
+ nsapi_size_or_error_t LWIP::socket_recvfrom (nsapi_socket_t handle, SocketAddress *address, void *data, nsapi_size_t size)
448
+ {
449
+ return socket_recvmsg (handle, address, data, size, NULL , 0 );
450
+
451
+ }
452
+
453
+ nsapi_size_or_error_t LWIP::socket_recvmsg (nsapi_socket_t handle, SocketAddress *address,
454
+ void *data, nsapi_size_t size,
455
+ nsapi_msghdr_t *control, nsapi_size_t control_size)
442
456
{
443
457
struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
444
- ip_addr_t ip_addr;
458
+ struct netbuf *buf;
459
+
460
+ err_t err = netconn_recv (s->conn , &buf);
461
+ if (err != ERR_OK) {
462
+ return err_remap (err);
463
+ }
464
+
465
+ if (address) {
466
+ nsapi_addr_t addr;
467
+ convert_lwip_addr_to_mbed (&addr, netbuf_fromaddr (buf));
468
+ address->set_addr (addr);
469
+ address->set_port (netbuf_fromport (buf));
470
+ }
471
+
472
+ if ((s->conn ->flags & NETCONN_FLAG_PKTINFO) && control && control_size >= sizeof (nsapi_pktinfo_t )) {
473
+ nsapi_pktinfo_t *pkt_info = reinterpret_cast <nsapi_pktinfo *>(control);
474
+ // Not optimal but sufficient. It should help the caller in not iterating over
475
+ // the control data structure
476
+ control->len = control_size;
477
+ control->level = NSAPI_SOCKET;
478
+ control->type = NSAPI_PKTINFO;
479
+ // retrieve the destination
480
+ convert_lwip_addr_to_mbed (&pkt_info->ipi_addr , netbuf_destaddr (buf));
481
+ // retrieve the interface id
482
+ pkt_info->ipi_ifindex = buf->p ->if_idx ;
483
+ }
484
+
485
+ u16_t recv = netbuf_copy (buf, data, (u16_t )size);
486
+ netbuf_delete (buf);
487
+
488
+ return recv;
489
+ }
490
+
491
+ nsapi_size_or_error_t LWIP::socket_sendmsg (nsapi_socket_t handle, const SocketAddress &address,
492
+ const void *data, nsapi_size_t size,
493
+ nsapi_msghdr_t *control, nsapi_size_t control_size)
494
+ {
495
+ struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
496
+ ip_addr_t ip_addr = {};
497
+
498
+ // Used for backup the bound address if the packet must be sent from a specific address,
499
+ ip_addr_t bound_addr = {};
500
+ ip_addr_t src_addr = {};
501
+
502
+ nsapi_pktinfo_t *pkt_info = nullptr ;
445
503
446
504
nsapi_addr_t addr = address.get_addr ();
447
505
if (!convert_mbed_addr_to_lwip (&ip_addr, &addr)) {
448
506
return NSAPI_ERROR_PARAMETER;
449
507
}
450
- struct netif *netif_ = netif_get_by_index (s->conn ->pcb .ip ->netif_idx );
508
+
509
+ // We try to extract the pktinfo from the header
510
+
511
+ if (control) {
512
+ MsgHeaderIterator it (control, control_size);
513
+ while (it.has_next ()) {
514
+ auto *hdr = it.next ();
515
+ if (hdr->level == NSAPI_SOCKET && hdr->type == NSAPI_PKTINFO) {
516
+ pkt_info = reinterpret_cast <nsapi_pktinfo_t *>(hdr);
517
+ break ;
518
+ }
519
+ }
520
+ }
521
+
522
+ if (pkt_info) {
523
+ if (!convert_mbed_addr_to_lwip (&src_addr, &pkt_info->ipi_addr )) {
524
+ return NSAPI_ERROR_PARAMETER;
525
+ }
526
+ }
527
+
528
+ struct netif *netif_ = nullptr ;
529
+
530
+ if (pkt_info) {
531
+ netif_ = netif_get_by_index (pkt_info->ipi_ifindex );
532
+ } else {
533
+ netif_ = netif_get_by_index (s->conn ->pcb .ip ->netif_idx );
534
+ }
451
535
if (!netif_) {
452
536
netif_ = &default_interface->netif ;
453
537
}
538
+
454
539
if (netif_) {
455
540
if ((addr.version == NSAPI_IPv4 && !get_ipv4_addr (netif_)) ||
456
541
(addr.version == NSAPI_IPv6 && !get_ipv6_addr (netif_) && !get_ipv6_link_local_addr (netif_))) {
457
542
return NSAPI_ERROR_PARAMETER;
458
543
}
459
544
}
545
+
460
546
struct netbuf *buf = netbuf_new ();
461
547
462
548
err_t err = netbuf_ref (buf, data, (u16_t )size);
@@ -465,36 +551,29 @@ nsapi_size_or_error_t LWIP::socket_sendto(nsapi_socket_t handle, const SocketAdd
465
551
return err_remap (err);
466
552
}
467
553
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);
554
+ // handle src destination if required
555
+ if (pkt_info) {
556
+ // Backup the bound address
557
+ ip_addr_copy (bound_addr, s->conn ->pcb .udp ->local_ip );
558
+ // replace it with the source address
559
+ if (!ip_addr_isany (&src_addr)) {
560
+ ip_addr_copy (s->conn ->pcb .udp ->local_ip , src_addr);
561
+ }
472
562
}
473
563
474
- return size;
475
- }
564
+ err = netconn_sendto (s->conn , buf, &ip_addr, address.get_port ());
476
565
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;
566
+ if (pkt_info) {
567
+ // restore bound address
568
+ ip_addr_copy (s-> conn -> pcb . udp -> local_ip , bound_addr) ;
569
+ }
481
570
482
- err_t err = netconn_recv (s-> conn , & buf);
571
+ netbuf_delete ( buf);
483
572
if (err != ERR_OK) {
484
573
return err_remap (err);
485
574
}
486
575
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;
576
+ return size;
498
577
}
499
578
500
579
int32_t LWIP::find_multicast_member (const struct mbed_lwip_socket *s, const nsapi_ip_mreq_t *imr)
@@ -687,6 +766,19 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co
687
766
}
688
767
s->conn ->pcb .ip ->tos = (u8_t )(*(const int *)optval);
689
768
return 0 ;
769
+
770
+ case NSAPI_PKTINFO:
771
+ // FIXME: Turn NETCONN_FLAG_PKTINFO off by default
772
+ if (optlen != sizeof (int )) {
773
+ return NSAPI_ERROR_UNSUPPORTED;
774
+ }
775
+ if (*(const int *)optval) {
776
+ s->conn ->flags |= NETCONN_FLAG_PKTINFO;
777
+ } else {
778
+ s->conn ->flags &= ~NETCONN_FLAG_PKTINFO;
779
+ }
780
+ return 0 ;
781
+
690
782
default :
691
783
return NSAPI_ERROR_UNSUPPORTED;
692
784
}
0 commit comments