1use crate::conversion::to_nb;
2use crate::SocketState;
3use embedded_nal::nb;
4use embedded_nal::{UdpClientStack, UdpFullStack};
5use std::io::{self, Error};
6use std::net::{self, IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
7
8pub struct UdpSocket {
9 state: SocketState<net::UdpSocket, net::UdpSocket>,
10}
11
12impl UdpSocket {
13 fn new() -> Self {
14 Self {
15 state: SocketState::new(),
16 }
17 }
18
19 #[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
31 pub fn as_raw_fd(&self) -> Option<std::os::fd::RawFd> {
32 use std::os::fd::AsRawFd;
33
34 Some(self.state.get_any().ok()?.as_raw_fd())
35 }
36}
37
38impl UdpClientStack for crate::Stack {
39 type UdpSocket = UdpSocket;
40 type Error = Error;
41
42 fn socket(&mut self) -> Result<Self::UdpSocket, Self::Error> {
43 Ok(UdpSocket::new())
44 }
45
46 fn connect(&mut self, socket: &mut Self::UdpSocket, remote: SocketAddr) -> std::io::Result<()> {
47 let any = match remote {
48 SocketAddr::V4(_) => SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0),
49 SocketAddr::V6(_) => SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0),
50 };
51
52 let sock = net::UdpSocket::bind(any)?;
53
54 sock.set_nonblocking(true)?;
55
56 sock.connect(remote)?;
57 socket.state = SocketState::Connected(sock);
58 Ok(())
59 }
60
61 fn send(&mut self, socket: &mut Self::UdpSocket, buffer: &[u8]) -> nb::Result<(), Self::Error> {
62 let sock = socket.state.get_running()?;
63 sock.send(buffer).map(drop).map_err(to_nb)
64 }
65
66 fn receive(
67 &mut self,
68 socket: &mut Self::UdpSocket,
69 buffer: &mut [u8],
70 ) -> nb::Result<(usize, SocketAddr), Self::Error> {
71 let sock = socket.state.get_any_mut()?;
72 sock.recv_from(buffer).map_err(to_nb)
73 }
74
75 fn close(&mut self, _: Self::UdpSocket) -> io::Result<()> {
76 Ok(())
82 }
83}
84
85impl UdpFullStack for crate::Stack {
86 fn bind(&mut self, socket: &mut UdpSocket, port: u16) -> Result<(), Error> {
87 let anyaddressthisport = SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), port);
88
89 let sock = net::UdpSocket::bind(anyaddressthisport)?;
90
91 sock.set_nonblocking(true)?;
92
93 socket.state = SocketState::Bound(sock);
94 Ok(())
95 }
96 fn send_to(
97 &mut self,
98 socket: &mut UdpSocket,
99 remote: SocketAddr,
100 buffer: &[u8],
101 ) -> Result<(), nb::Error<Error>> {
102 let sock = socket.state.get_bound()?;
103 sock.send_to(buffer, remote).map(drop).map_err(to_nb)
104 }
105}