1use crate::conversion;
4use core::net::SocketAddr;
5use std::io::Error;
6
7use std::os::fd::AsRawFd;
8
9pub struct ConnectedSocket(async_io::Async<std::net::UdpSocket>);
10pub struct UniquelyBoundSocket {
11 socket: async_io::Async<std::net::UdpSocket>,
12 bound_address: SocketAddr,
15}
16pub struct MultiplyBoundSocket {
17 socket: async_io::Async<std::net::UdpSocket>,
18 port: u16,
21}
22
23impl embedded_nal_async::UdpStack for crate::Stack {
24 type Error = Error;
25 type Connected = ConnectedSocket;
26 type UniquelyBound = UniquelyBoundSocket;
27 type MultiplyBound = MultiplyBoundSocket;
28
29 async fn connect_from(
30 &self,
31 local: SocketAddr,
32 remote: SocketAddr,
33 ) -> Result<(SocketAddr, Self::Connected), Self::Error> {
34 let sock = async_io::Async::<std::net::UdpSocket>::bind(local)?;
35
36 sock.get_ref().connect(remote)?;
37
38 Ok((sock.get_ref().local_addr()?, ConnectedSocket(sock)))
39 }
40
41 async fn bind_single(
42 &self,
43 local: SocketAddr,
44 ) -> Result<(SocketAddr, Self::UniquelyBound), Self::Error> {
45 let sock = async_io::Async::<std::net::UdpSocket>::bind(local)?;
46
47 let final_local = sock.get_ref().local_addr()?;
48
49 Ok((
50 final_local,
51 UniquelyBoundSocket {
52 socket: sock,
53 bound_address: final_local,
54 },
55 ))
56 }
57
58 async fn bind_multiple(
59 &self,
60 local: core::net::SocketAddr,
61 ) -> Result<Self::MultiplyBound, Self::Error> {
62 let is_v4 = matches!(&local, core::net::SocketAddr::V4(_));
63
64 let sock = async_io::Async::<std::net::UdpSocket>::bind(local)?;
65
66 let plain_sock = sock.get_ref();
67
68 if is_v4 {
69 nix::sys::socket::setsockopt(
70 &plain_sock,
71 nix::sys::socket::sockopt::Ipv4PacketInfo,
72 &true,
73 )?;
74 } else {
75 nix::sys::socket::setsockopt(
76 &plain_sock,
77 nix::sys::socket::sockopt::Ipv6RecvPacketInfo,
78 &true,
79 )?;
80 }
81
82 let mut local_port = local.port();
83 if local_port == 0 {
84 local_port = plain_sock.local_addr()?.port();
85 }
86
87 Ok(MultiplyBoundSocket {
88 socket: sock,
89 port: local_port,
90 })
91 }
92}
93
94impl embedded_nal_async::ConnectedUdp for ConnectedSocket {
95 type Error = Error;
96
97 async fn send(&mut self, data: &[u8]) -> Result<(), Self::Error> {
98 let sent_len = self.0.send(data).await?;
99 assert!(
100 sent_len == data.len(),
101 "Datagram was not sent in a single operation"
102 );
103 Ok(())
104 }
105
106 async fn receive_into(&mut self, buffer: &mut [u8]) -> Result<usize, Self::Error> {
107 self.0.recv(buffer).await
108 }
109}
110
111impl embedded_nal_async::UnconnectedUdp for UniquelyBoundSocket {
112 type Error = Error;
113
114 async fn send(
115 &mut self,
116 local: core::net::SocketAddr,
117 remote: core::net::SocketAddr,
118 data: &[u8],
119 ) -> Result<(), Self::Error> {
120 debug_assert!(
121 local == self.bound_address,
122 "A socket created from bind_single must always provide its original local address (or the one returned from a receive) in send"
123 );
124 let sent_len = self.socket.send_to(data, remote).await?;
125 assert!(
126 sent_len == data.len(),
127 "Datagram was not sent in a single operation"
128 );
129 Ok(())
130 }
131
132 async fn receive_into(
133 &mut self,
134 buffer: &mut [u8],
135 ) -> Result<(usize, core::net::SocketAddr, core::net::SocketAddr), Self::Error> {
136 let (length, remote) = self.socket.recv_from(buffer).await?;
137 Ok((length, self.bound_address, remote))
138 }
139}
140
141impl embedded_nal_async::UnconnectedUdp for MultiplyBoundSocket {
142 type Error = Error;
143
144 async fn send(
145 &mut self,
146 local: core::net::SocketAddr,
147 remote: core::net::SocketAddr,
148 data: &[u8],
149 ) -> Result<(), Self::Error> {
150 if local.port() != 0 {
151 debug_assert_eq!(
152 local.port(),
153 self.port,
154 "Packets can only be sent from the locally bound to port"
155 );
156 }
157 match remote {
158 core::net::SocketAddr::V6(remote) => {
160 let remote = nix::sys::socket::SockaddrIn6::from(remote);
162 let local_pktinfo = conversion::IpAddr(local.ip()).into();
163 let control = [nix::sys::socket::ControlMessage::Ipv6PacketInfo(
164 &local_pktinfo,
165 )];
166 self.socket
167 .write_with(|s| {
168 let sent_len = nix::sys::socket::sendmsg(
169 s.as_raw_fd(),
170 &[std::io::IoSlice::new(data)],
171 &control,
173 nix::sys::socket::MsgFlags::empty(),
174 Some(&remote),
175 )?;
176 assert!(
177 sent_len == data.len(),
178 "Datagram was not sent in a single operation"
179 );
180 Ok(())
181 })
182 .await
183 }
184 core::net::SocketAddr::V4(remote) => {
185 let remote = nix::sys::socket::SockaddrIn::from(remote);
187 let local_pktinfo = conversion::IpAddr(local.ip()).into();
188 let control = [nix::sys::socket::ControlMessage::Ipv4PacketInfo(
189 &local_pktinfo,
190 )];
191 self.socket
192 .write_with(|s| {
193 let sent_len = nix::sys::socket::sendmsg(
194 s.as_raw_fd(),
195 &[std::io::IoSlice::new(data)],
196 &control,
198 nix::sys::socket::MsgFlags::empty(),
199 Some(&remote),
200 )?;
201 assert!(
202 sent_len == data.len(),
203 "Datagram was not sent in a single operation"
204 );
205 Ok(())
206 })
207 .await
208 }
209 }
210 }
211
212 async fn receive_into(
213 &mut self,
214 buffer: &mut [u8],
215 ) -> Result<(usize, core::net::SocketAddr, core::net::SocketAddr), Self::Error> {
216 let (length, remote, local) = self.socket.read_with(|s| {
217 let mut iov = [std::io::IoSliceMut::new(buffer)];
218 let mut cmsg = nix::cmsg_space!(nix::libc::in6_pktinfo);
219 let received = nix::sys::socket::recvmsg(
220 s.as_raw_fd(),
221 &mut iov,
222 Some(&mut cmsg),
223 nix::sys::socket::MsgFlags::MSG_TRUNC,
224 )
225 .map_err(Error::from)?;
226 let local = match received.cmsgs()?.next() {
227 Some(nix::sys::socket::ControlMessageOwned::Ipv6PacketInfo(pi)) => {
228 SocketAddr::new(
229 conversion::IpAddr::from(pi).0,
230 self.port,
231 )
232 },
233 Some(nix::sys::socket::ControlMessageOwned::Ipv4PacketInfo(pi)) => {
234 SocketAddr::new(
235 conversion::IpAddr::from(pi).0,
236 self.port,
237 )
238 },
239 _ => panic!("Operating system failed to send IPv4/IPv6 packet info after acknowledging the socket option")
240 };
241 Ok((received.bytes, received.address, local))
242 }).await?;
243
244 let remote: nix::sys::socket::SockaddrStorage =
245 remote.expect("recvmsg on UDP always returns a remote address");
246 let remote = match (remote.as_sockaddr_in6(), remote.as_sockaddr_in()) {
248 (Some(remote), None) => std::net::SocketAddr::V6(std::net::SocketAddrV6::new(
249 remote.ip(),
250 remote.port(),
251 remote.flowinfo(),
252 remote.scope_id(),
253 )),
254 (None, Some(remote)) => {
255 std::net::SocketAddr::V4(std::net::SocketAddrV4::new(remote.ip(), remote.port()))
256 }
257 _ => panic!("Unexpected address type"),
258 };
259
260 Ok((length, local, remote))
262 }
263}