Skip to main content

edge_nal_std/
lib.rs

1#![allow(async_fn_in_trait)]
2#![warn(clippy::large_futures)]
3#![allow(clippy::uninlined_format_args)]
4#![allow(unknown_lints)]
5
6use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
7use core::ops::Deref;
8use core::pin::pin;
9
10use std::io;
11use std::net::{self, Shutdown, TcpStream, ToSocketAddrs, UdpSocket as StdUdpSocket};
12
13#[cfg(not(feature = "async-io-mini"))]
14use async_io::Async;
15#[cfg(feature = "async-io-mini")]
16use async_io_mini::Async;
17
18use futures_lite::io::{AsyncReadExt, AsyncWriteExt};
19
20use embedded_io_async::{ErrorType, Read, Write};
21
22use edge_nal::{
23    AddrType, Dns, MulticastV4, MulticastV6, Readable, TcpAccept, TcpBind, TcpConnect, TcpShutdown,
24    TcpSplit, UdpBind, UdpConnect, UdpReceive, UdpSend, UdpSplit, UdpSplitMulticast,
25};
26
27#[cfg(any(target_os = "linux", target_os = "android"))]
28pub use raw::*;
29
30/// The STD network stack implementation.
31///
32/// This uses the standard library's networking types under the hood,
33/// wrapped in async-io's `Async` type for async support.
34///
35/// The type is `Copy` and `Clone`, so it can be easily passed around.
36#[derive(Default, Copy, Clone)]
37pub struct Stack(());
38
39impl Stack {
40    /// Create a new STD network stack instance.
41    pub const fn new() -> Self {
42        Self(())
43    }
44}
45
46impl TcpConnect for Stack {
47    type Error = io::Error;
48
49    type Socket<'a>
50        = TcpSocket
51    where
52        Self: 'a;
53
54    async fn connect(&self, remote: SocketAddr) -> Result<Self::Socket<'_>, Self::Error> {
55        let socket = Async::<TcpStream>::connect(remote).await?;
56
57        Ok(TcpSocket(socket))
58    }
59}
60
61impl TcpBind for Stack {
62    type Error = io::Error;
63
64    type Accept<'a>
65        = TcpAcceptor
66    where
67        Self: 'a;
68
69    async fn bind(&self, local: SocketAddr) -> Result<Self::Accept<'_>, Self::Error> {
70        let acceptor = Async::<net::TcpListener>::bind(local).map(TcpAcceptor)?;
71
72        Ok(acceptor)
73    }
74}
75
76/// The TCP acceptor type for the STD network stack.
77pub struct TcpAcceptor(Async<net::TcpListener>);
78
79impl TcpAccept for TcpAcceptor {
80    type Error = io::Error;
81
82    type Socket<'a>
83        = TcpSocket
84    where
85        Self: 'a;
86
87    #[cfg(not(target_os = "espidf"))]
88    async fn accept(&self) -> Result<(SocketAddr, Self::Socket<'_>), Self::Error> {
89        let socket = self.0.accept().await.map(|(socket, _)| socket)?;
90
91        Ok((socket.as_ref().peer_addr()?, TcpSocket(socket)))
92    }
93
94    #[cfg(target_os = "espidf")]
95    async fn accept(&self) -> Result<(SocketAddr, Self::Socket<'_>), Self::Error> {
96        // ESP IDF (lwIP actually) does not really support `select`-ing on
97        // socket accept: https://groups.google.com/g/osdeve_mirror_tcpip_lwip/c/Vsz7SVa6a2M
98        //
99        // If we do this, `select` would block and not return with our accepting socket `fd`
100        // marked as ready even if our accepting socket has a pending connection.
101        //
102        // (Note also that since the time when the above link was posted on the internet,
103        // the lwIP `accept` API has improved a bit in that it would now return `EWOULDBLOCK`
104        // instead of blocking indefinitely
105        // - and we take advantage of that in the "async" implementation below.)
106        //
107        // The workaround below is not ideal in that
108        // it uses a timer to poll the socket, but it avoids spinning a hidden,
109        // separate thread just to accept connections - which would be the alternative.
110        loop {
111            match self.0.as_ref().accept() {
112                Ok((socket, _)) => break Ok((socket.peer_addr()?, TcpSocket(Async::new(socket)?))),
113                Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
114                    #[cfg(not(feature = "async-io-mini"))]
115                    use async_io::Timer;
116                    #[cfg(feature = "async-io-mini")]
117                    use async_io_mini::Timer;
118
119                    Timer::after(core::time::Duration::from_millis(20)).await;
120                }
121                Err(err) => break Err(err),
122            }
123        }
124    }
125}
126
127/// The TCP socket type for the STD network stack.
128pub struct TcpSocket(Async<TcpStream>);
129
130impl TcpSocket {
131    /// Create a new TCP socket from the given async TCP stream.
132    ///
133    /// # Arguments
134    /// - `socket`: The async TCP stream to wrap.
135    pub const fn new(socket: Async<TcpStream>) -> Self {
136        Self(socket)
137    }
138
139    /// Release the underlying async TCP stream.
140    pub fn release(self) -> Async<TcpStream> {
141        self.0
142    }
143}
144
145impl Deref for TcpSocket {
146    type Target = Async<TcpStream>;
147
148    fn deref(&self) -> &Self::Target {
149        &self.0
150    }
151}
152
153impl ErrorType for TcpSocket {
154    type Error = io::Error;
155}
156
157impl Read for TcpSocket {
158    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
159        self.0.read(buf).await
160    }
161}
162
163impl Write for TcpSocket {
164    async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
165        self.0.write(buf).await
166    }
167
168    async fn flush(&mut self) -> Result<(), Self::Error> {
169        self.0.flush().await
170    }
171}
172
173impl Readable for TcpSocket {
174    async fn readable(&mut self) -> Result<(), Self::Error> {
175        self.0.readable().await
176    }
177}
178
179impl ErrorType for &TcpSocket {
180    type Error = io::Error;
181}
182
183impl Read for &TcpSocket {
184    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
185        (&self.0).read(buf).await
186    }
187}
188
189impl Write for &TcpSocket {
190    async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
191        (&self.0).write(buf).await
192    }
193
194    async fn flush(&mut self) -> Result<(), Self::Error> {
195        (&self.0).flush().await
196    }
197}
198
199impl Readable for &TcpSocket {
200    async fn readable(&mut self) -> Result<(), Self::Error> {
201        self.0.readable().await
202    }
203}
204
205impl TcpSplit for TcpSocket {
206    type Read<'a>
207        = &'a TcpSocket
208    where
209        Self: 'a;
210
211    type Write<'a>
212        = &'a TcpSocket
213    where
214        Self: 'a;
215
216    fn split(&mut self) -> (Self::Read<'_>, Self::Write<'_>) {
217        let socket = &*self;
218
219        (socket, socket)
220    }
221}
222
223impl TcpShutdown for TcpSocket {
224    async fn close(&mut self, what: edge_nal::Close) -> Result<(), Self::Error> {
225        match what {
226            edge_nal::Close::Read => self.0.as_ref().shutdown(Shutdown::Read)?,
227            edge_nal::Close::Write => self.0.as_ref().shutdown(Shutdown::Write)?,
228            edge_nal::Close::Both => self.0.as_ref().shutdown(Shutdown::Both)?,
229        }
230
231        Ok(())
232    }
233
234    async fn abort(&mut self) -> Result<(), Self::Error> {
235        // No-op, STD will abort the socket on drop anyway
236
237        Ok(())
238    }
239}
240
241impl UdpConnect for Stack {
242    type Error = io::Error;
243
244    type Socket<'a>
245        = UdpSocket
246    where
247        Self: 'a;
248
249    async fn connect(
250        &self,
251        local: SocketAddr,
252        remote: SocketAddr,
253    ) -> Result<Self::Socket<'_>, Self::Error> {
254        let socket = Async::<StdUdpSocket>::bind(local)?;
255
256        socket.as_ref().connect(remote)?;
257
258        Ok(UdpSocket(socket))
259    }
260}
261
262impl UdpBind for Stack {
263    type Error = io::Error;
264
265    type Socket<'a>
266        = UdpSocket
267    where
268        Self: 'a;
269
270    async fn bind(&self, local: SocketAddr) -> Result<Self::Socket<'_>, Self::Error> {
271        let socket = Async::<StdUdpSocket>::bind(local)?;
272
273        socket.as_ref().set_broadcast(true)?;
274
275        Ok(UdpSocket(socket))
276    }
277}
278
279/// The UDP socket type for the STD network stack.
280pub struct UdpSocket(Async<StdUdpSocket>);
281
282impl UdpSocket {
283    /// Create a new UDP socket from the given async UDP socket.
284    ///
285    /// # Arguments
286    /// - `socket`: The async UDP socket to wrap.
287    pub const fn new(socket: Async<StdUdpSocket>) -> Self {
288        Self(socket)
289    }
290
291    /// Release the underlying async UDP socket.
292    pub fn release(self) -> Async<StdUdpSocket> {
293        self.0
294    }
295
296    /// Join a multicast group for IPv4.
297    ///
298    /// # Arguments
299    /// - `multiaddr`: The multicast address to join.
300    /// - `interface`: The interface address to use.
301    pub fn join_multicast_v4(
302        &self,
303        multiaddr: &Ipv4Addr,
304        interface: &Ipv4Addr,
305    ) -> Result<(), io::Error> {
306        #[cfg(not(target_os = "espidf"))]
307        self.as_ref().join_multicast_v4(multiaddr, interface)?;
308
309        #[cfg(target_os = "espidf")]
310        self.setsockopt_ipproto_ip(
311            multiaddr, interface, 3, /* IP_ADD_MEMBERSHIP in ESP IDF*/
312        )?;
313
314        Ok(())
315    }
316
317    /// Leave a multicast group for IPv4.
318    ///
319    /// # Arguments
320    /// - `multiaddr`: The multicast address to leave.
321    /// - `interface`: The interface address to use.
322    pub fn leave_multicast_v4(
323        &self,
324        multiaddr: &Ipv4Addr,
325        interface: &Ipv4Addr,
326    ) -> Result<(), io::Error> {
327        #[cfg(not(target_os = "espidf"))]
328        self.as_ref().leave_multicast_v4(multiaddr, interface)?;
329
330        #[cfg(target_os = "espidf")]
331        self.setsockopt_ipproto_ip(
332            multiaddr, interface, 4, /* IP_LEAVE_MEMBERSHIP in ESP IDF*/
333        )?;
334
335        Ok(())
336    }
337
338    #[cfg(target_os = "espidf")]
339    pub fn setsockopt_ipproto_ip(
340        &self,
341        multiaddr: &Ipv4Addr,
342        interface: &Ipv4Addr,
343        option: u32,
344    ) -> Result<(), io::Error> {
345        // join_multicast_v4() is broken for ESP-IDF due to IP_ADD_MEMBERSHIP being wrongly defined to 11,
346        // while it should be 3: https://github.com/rust-lang/libc/blob/main/src/unix/newlib/mod.rs#L568
347        //
348        // leave_multicast_v4() is broken for ESP-IDF due to IP_ADD_MEMBERSHIP being wrongly defined to 12,
349        // while it should be 4: https://github.com/rust-lang/libc/blob/main/src/unix/newlib/mod.rs#L569
350
351        let mreq = sys::ip_mreq {
352            imr_multiaddr: sys::in_addr {
353                s_addr: u32::from_ne_bytes(multiaddr.octets()),
354            },
355            imr_interface: sys::in_addr {
356                s_addr: u32::from_ne_bytes(interface.octets()),
357            },
358        };
359
360        use std::os::fd::AsRawFd;
361
362        syscall_los!(unsafe {
363            sys::setsockopt(
364                self.0.as_raw_fd(),
365                sys::IPPROTO_IP as _,
366                option as _,
367                &mreq as *const _ as *const _,
368                core::mem::size_of::<sys::ip_mreq>() as _,
369            )
370        })?;
371
372        Ok(())
373    }
374}
375
376impl Deref for UdpSocket {
377    type Target = Async<StdUdpSocket>;
378
379    fn deref(&self) -> &Self::Target {
380        &self.0
381    }
382}
383
384impl ErrorType for &UdpSocket {
385    type Error = io::Error;
386}
387
388impl UdpReceive for &UdpSocket {
389    async fn receive(&mut self, buffer: &mut [u8]) -> Result<(usize, SocketAddr), Self::Error> {
390        let remote = self.0.as_ref().peer_addr();
391
392        let (len, remote) = if let Ok(remote) = remote {
393            // Connected socket
394            let fut = pin!(self.0.recv(buffer));
395            let len = fut.await?;
396
397            (len, remote)
398        } else {
399            // Unconnected socket
400            let fut = pin!(self.0.recv_from(buffer));
401            let (len, remote) = fut.await?;
402
403            (len, remote)
404        };
405
406        Ok((len, remote))
407    }
408}
409
410impl UdpSend for &UdpSocket {
411    async fn send(&mut self, remote: SocketAddr, data: &[u8]) -> Result<(), Self::Error> {
412        let is_remote = self.0.as_ref().peer_addr().is_ok();
413
414        if is_remote {
415            // Connected socket
416            let mut offset = 0;
417
418            loop {
419                let fut = pin!(self.0.send(&data[offset..]));
420                offset += fut.await?;
421
422                if offset == data.len() {
423                    break;
424                }
425            }
426        } else {
427            // Unconnected socket
428            let mut offset = 0;
429
430            loop {
431                let fut = pin!(self.0.send_to(&data[offset..], remote));
432                offset += fut.await?;
433
434                if offset == data.len() {
435                    break;
436                }
437            }
438        }
439
440        Ok(())
441    }
442}
443
444impl MulticastV4 for &UdpSocket {
445    async fn join_v4(
446        &mut self,
447        multicast_addr: Ipv4Addr,
448        interface: Ipv4Addr,
449    ) -> Result<(), Self::Error> {
450        self.join_multicast_v4(&multicast_addr, &interface)
451    }
452
453    async fn leave_v4(
454        &mut self,
455        multicast_addr: Ipv4Addr,
456        interface: Ipv4Addr,
457    ) -> Result<(), Self::Error> {
458        self.leave_multicast_v4(&multicast_addr, &interface)
459    }
460}
461
462impl MulticastV6 for &UdpSocket {
463    async fn join_v6(
464        &mut self,
465        multicast_addr: Ipv6Addr,
466        interface: u32,
467    ) -> Result<(), Self::Error> {
468        self.0
469            .as_ref()
470            .join_multicast_v6(&multicast_addr, interface)
471    }
472
473    async fn leave_v6(
474        &mut self,
475        multicast_addr: Ipv6Addr,
476        interface: u32,
477    ) -> Result<(), Self::Error> {
478        self.0
479            .as_ref()
480            .leave_multicast_v6(&multicast_addr, interface)
481    }
482}
483
484impl Readable for &UdpSocket {
485    async fn readable(&mut self) -> Result<(), Self::Error> {
486        self.0.readable().await
487    }
488}
489
490impl ErrorType for UdpSocket {
491    type Error = io::Error;
492}
493
494impl UdpReceive for UdpSocket {
495    async fn receive(&mut self, buffer: &mut [u8]) -> Result<(usize, SocketAddr), Self::Error> {
496        let mut rself = &*self;
497
498        let fut = pin!(rself.receive(buffer));
499        fut.await
500    }
501}
502
503impl UdpSend for UdpSocket {
504    async fn send(&mut self, remote: SocketAddr, data: &[u8]) -> Result<(), Self::Error> {
505        let mut rself = &*self;
506
507        let fut = pin!(rself.send(remote, data));
508        fut.await
509    }
510}
511
512impl MulticastV4 for UdpSocket {
513    async fn join_v4(
514        &mut self,
515        multicast_addr: Ipv4Addr,
516        interface: Ipv4Addr,
517    ) -> Result<(), Self::Error> {
518        self.join_multicast_v4(&multicast_addr, &interface)
519    }
520
521    async fn leave_v4(
522        &mut self,
523        multicast_addr: Ipv4Addr,
524        interface: Ipv4Addr,
525    ) -> Result<(), Self::Error> {
526        self.leave_multicast_v4(&multicast_addr, &interface)
527    }
528}
529
530impl MulticastV6 for UdpSocket {
531    async fn join_v6(
532        &mut self,
533        multicast_addr: Ipv6Addr,
534        interface: u32,
535    ) -> Result<(), Self::Error> {
536        self.0
537            .as_ref()
538            .join_multicast_v6(&multicast_addr, interface)
539    }
540
541    async fn leave_v6(
542        &mut self,
543        multicast_addr: Ipv6Addr,
544        interface: u32,
545    ) -> Result<(), Self::Error> {
546        self.0
547            .as_ref()
548            .leave_multicast_v6(&multicast_addr, interface)
549    }
550}
551
552impl Readable for UdpSocket {
553    async fn readable(&mut self) -> Result<(), Self::Error> {
554        let mut rself = &*self;
555
556        let fut = pin!(rself.readable());
557        fut.await
558    }
559}
560
561impl UdpSplit for UdpSocket {
562    type Receive<'a>
563        = &'a Self
564    where
565        Self: 'a;
566
567    type Send<'a>
568        = &'a Self
569    where
570        Self: 'a;
571
572    fn split(&mut self) -> (Self::Receive<'_>, Self::Send<'_>) {
573        let socket = &*self;
574
575        (socket, socket)
576    }
577}
578
579impl UdpSplitMulticast for UdpSocket {
580    type MulticastV4<'a>
581        = &'a Self
582    where
583        Self: 'a;
584
585    type MulticastV6<'a>
586        = &'a Self
587    where
588        Self: 'a;
589
590    fn split_multicast(
591        &mut self,
592    ) -> (
593        Self::Receive<'_>,
594        Self::Send<'_>,
595        Self::MulticastV4<'_>,
596        Self::MulticastV6<'_>,
597    ) {
598        let socket = &*self;
599
600        (socket, socket, socket, socket)
601    }
602}
603
604impl Dns for Stack {
605    type Error = io::Error;
606
607    async fn get_host_by_name(
608        &self,
609        host: &str,
610        addr_type: AddrType,
611    ) -> Result<IpAddr, Self::Error> {
612        let host = host.to_string();
613
614        dns_lookup_host(&host, addr_type)
615    }
616
617    async fn get_host_by_address(
618        &self,
619        _addr: IpAddr,
620        _result: &mut [u8],
621    ) -> Result<usize, Self::Error> {
622        Err(io::ErrorKind::Unsupported.into())
623    }
624}
625
626/// Perform a DNS lookup for the given host and address type.
627fn dns_lookup_host(host: &str, addr_type: AddrType) -> Result<IpAddr, io::Error> {
628    (host, 0_u16)
629        .to_socket_addrs()?
630        .find(|addr| match addr_type {
631            AddrType::IPv4 => matches!(addr, std::net::SocketAddr::V4(_)),
632            AddrType::IPv6 => matches!(addr, std::net::SocketAddr::V6(_)),
633            AddrType::Either => true,
634        })
635        .map(|addr| match addr {
636            std::net::SocketAddr::V4(v4) => v4.ip().octets().into(),
637            std::net::SocketAddr::V6(v6) => v6.ip().octets().into(),
638        })
639        .ok_or_else(|| io::ErrorKind::AddrNotAvailable.into())
640}
641
642// TODO: Figure out if the RAW socket implementation can be used on any other OS.
643// It seems, that would be difficult on Darwin; wondering about the other BSDs though?
644#[cfg(any(target_os = "linux", target_os = "android"))]
645mod raw {
646    use core::ops::Deref;
647    use core::pin::pin;
648
649    use std::io::{self, ErrorKind};
650    use std::os::fd::{AsFd, AsRawFd};
651
652    #[cfg(not(feature = "async-io-mini"))]
653    use async_io::Async;
654    #[cfg(feature = "async-io-mini")]
655    use async_io_mini::Async;
656
657    use edge_nal::{MacAddr, RawBind, RawReceive, RawSend, RawSplit, Readable};
658    use embedded_io_async::ErrorType;
659
660    use crate::sys;
661    use crate::syscall_los;
662
663    /// The RAW interface binding type for Linux.
664    #[derive(Default, Copy, Clone)]
665    pub struct Interface(u32);
666
667    impl Interface {
668        /// Create a new RAW interface binding for the given interface index.
669        pub const fn new(interface: u32) -> Self {
670            Self(interface)
671        }
672    }
673
674    impl RawBind for Interface {
675        type Error = io::Error;
676
677        type Socket<'a>
678            = RawSocket
679        where
680            Self: 'a;
681
682        async fn bind(&self) -> Result<Self::Socket<'_>, Self::Error> {
683            let socket = syscall_los!(unsafe {
684                sys::socket(
685                    sys::PF_PACKET,
686                    sys::SOCK_DGRAM,
687                    (sys::ETH_P_IP as u16).to_be() as _,
688                )
689            })?;
690
691            let sockaddr = sys::sockaddr_ll {
692                sll_family: sys::AF_PACKET as _,
693                sll_protocol: (sys::ETH_P_IP as u16).to_be() as _,
694                sll_ifindex: self.0 as _,
695                sll_hatype: 0,
696                sll_pkttype: 0,
697                sll_halen: 0,
698                sll_addr: Default::default(),
699            };
700
701            syscall_los!(unsafe {
702                sys::bind(
703                    socket,
704                    &sockaddr as *const _ as *const _,
705                    core::mem::size_of::<sys::sockaddr_ll>() as _,
706                )
707            })?;
708
709            // TODO
710            // syscall_los!(unsafe {
711            //     sys::setsockopt(socket, sys::SOL_PACKET, sys::PACKET_AUXDATA, &1_u32 as *const _ as *const _, 4)
712            // })?;
713
714            let socket = {
715                use std::os::fd::FromRawFd;
716
717                unsafe { std::net::UdpSocket::from_raw_fd(socket) }
718            };
719
720            socket.set_broadcast(true)?;
721
722            Ok(RawSocket(Async::new(socket)?, self.0 as _))
723        }
724    }
725
726    /// The RAW socket type for Linux.
727    pub struct RawSocket(Async<std::net::UdpSocket>, u32);
728
729    impl RawSocket {
730        /// Create a new RAW socket from the given async UDP socket and interface index.
731        ///
732        /// # Arguments
733        /// - `socket`: The async UDP socket to wrap.
734        /// - `interface`: The interface index.
735        pub const fn new(socket: Async<std::net::UdpSocket>, interface: u32) -> Self {
736            Self(socket, interface)
737        }
738
739        /// Release the underlying async UDP socket and interface index.
740        pub fn release(self) -> (Async<std::net::UdpSocket>, u32) {
741            (self.0, self.1)
742        }
743    }
744
745    impl Deref for RawSocket {
746        type Target = Async<std::net::UdpSocket>;
747
748        fn deref(&self) -> &Self::Target {
749            &self.0
750        }
751    }
752
753    impl ErrorType for &RawSocket {
754        type Error = io::Error;
755    }
756
757    impl RawReceive for &RawSocket {
758        async fn receive(&mut self, buffer: &mut [u8]) -> Result<(usize, MacAddr), Self::Error> {
759            let fut = pin!(self.0.read_with(|io| {
760                let mut storage: sys::sockaddr_storage = unsafe { core::mem::zeroed() };
761                let mut addrlen = core::mem::size_of_val(&storage) as sys::socklen_t;
762
763                let ret = syscall_los!(unsafe {
764                    sys::recvfrom(
765                        io.as_fd().as_raw_fd(),
766                        buffer.as_mut_ptr() as *mut _,
767                        buffer.len(),
768                        0,
769                        &mut storage as *mut _ as *mut _,
770                        &mut addrlen,
771                    )
772                })?;
773
774                let sockaddr = as_sockaddr_ll(&storage, addrlen as usize)?;
775
776                let mut mac = [0; 6];
777                mac.copy_from_slice(&sockaddr.sll_addr[..6]);
778
779                Ok((ret as usize, mac))
780            }));
781
782            fut.await
783        }
784    }
785
786    impl RawSend for &RawSocket {
787        async fn send(&mut self, mac: MacAddr, data: &[u8]) -> Result<(), Self::Error> {
788            let mut sockaddr = sys::sockaddr_ll {
789                sll_family: sys::AF_PACKET as _,
790                sll_protocol: (sys::ETH_P_IP as u16).to_be() as _,
791                sll_ifindex: self.1 as _,
792                sll_hatype: 0,
793                sll_pkttype: 0,
794                sll_halen: 0,
795                sll_addr: Default::default(),
796            };
797
798            sockaddr.sll_halen = mac.len() as _;
799            sockaddr.sll_addr[..mac.len()].copy_from_slice(&mac);
800
801            let fut = pin!(self.0.write_with(|io| {
802                let len = core::cmp::min(data.len(), u16::MAX as usize);
803
804                let ret = syscall_los!(unsafe {
805                    sys::sendto(
806                        io.as_fd().as_raw_fd(),
807                        data.as_ptr() as *const _,
808                        len,
809                        sys::MSG_NOSIGNAL,
810                        &sockaddr as *const _ as *const _,
811                        core::mem::size_of::<sys::sockaddr_ll>() as _,
812                    )
813                })?;
814                Ok(ret as usize)
815            }));
816
817            let len = fut.await?;
818
819            assert_eq!(len, data.len());
820
821            Ok(())
822        }
823    }
824
825    impl Readable for &RawSocket {
826        async fn readable(&mut self) -> Result<(), Self::Error> {
827            self.0.readable().await
828        }
829    }
830
831    impl ErrorType for RawSocket {
832        type Error = io::Error;
833    }
834
835    impl RawReceive for RawSocket {
836        async fn receive(&mut self, buffer: &mut [u8]) -> Result<(usize, MacAddr), Self::Error> {
837            let mut rself = &*self;
838
839            let fut = pin!(rself.receive(buffer));
840
841            fut.await
842        }
843    }
844
845    impl RawSend for RawSocket {
846        async fn send(&mut self, mac: MacAddr, data: &[u8]) -> Result<(), Self::Error> {
847            let mut rself = &*self;
848
849            let fut = pin!(rself.send(mac, data));
850
851            fut.await
852        }
853    }
854
855    impl RawSplit for RawSocket {
856        type Receive<'a>
857            = &'a Self
858        where
859            Self: 'a;
860
861        type Send<'a>
862            = &'a Self
863        where
864            Self: 'a;
865
866        fn split(&mut self) -> (Self::Receive<'_>, Self::Send<'_>) {
867            let socket = &*self;
868
869            (socket, socket)
870        }
871    }
872
873    impl Readable for RawSocket {
874        async fn readable(&mut self) -> Result<(), Self::Error> {
875            self.0.readable().await
876        }
877    }
878
879    fn as_sockaddr_ll(
880        storage: &sys::sockaddr_storage,
881        len: usize,
882    ) -> io::Result<&sys::sockaddr_ll> {
883        match storage.ss_family as core::ffi::c_int {
884            sys::AF_PACKET => {
885                assert!(len >= core::mem::size_of::<sys::sockaddr_ll>());
886                Ok(unsafe { (storage as *const _ as *const sys::sockaddr_ll).as_ref() }.unwrap())
887            }
888            _ => Err(io::Error::new(ErrorKind::InvalidInput, "invalid argument")),
889        }
890    }
891}
892
893#[cfg(any(target_os = "linux", target_os = "android", target_os = "espidf"))]
894mod sys {
895    pub use libc::*;
896
897    #[macro_export]
898    macro_rules! syscall {
899        ($ret:expr) => {{
900            let result = $ret;
901
902            if result != 0 {
903                Err(::std::io::Error::from_raw_os_error(result))
904            } else {
905                Ok(result)
906            }
907        }};
908    }
909
910    #[macro_export]
911    macro_rules! syscall_los {
912        ($ret:expr) => {{
913            let result = $ret;
914
915            if result == -1 {
916                Err(::std::io::Error::last_os_error())
917            } else {
918                Ok(result)
919            }
920        }};
921    }
922
923    #[macro_export]
924    macro_rules! syscall_los_eagain {
925        ($ret:expr) => {{
926            #[allow(unreachable_patterns)]
927            match syscall_los!($ret) {
928                Ok(_) => Ok(()),
929                Err(e)
930                    if matches!(
931                        e.raw_os_error(),
932                        Some(sys::EINPROGRESS) | Some(sys::EAGAIN) | Some(sys::EWOULDBLOCK)
933                    ) =>
934                {
935                    Ok(())
936                }
937                Err(e) => Err(e),
938            }?;
939
940            Ok::<_, io::Error>(())
941        }};
942    }
943}