1use core::fmt::Display;
4use core::fmt::Formatter;
5use core::net::SocketAddr;
6
7#[expect(async_fn_in_trait)]
32pub trait UdpSocket {
33 async fn bind(&mut self, address: SocketAddr) -> Result<(), Error>;
37
38 fn local_addr(&self) -> Result<SocketAddr, Error>;
40
41 async fn recv_from(&self, buffer: &mut [u8]) -> Result<(usize, SocketAddr), Error>;
46
47 async fn send_to(&self, buffer: &[u8], address: SocketAddr) -> Result<usize, Error>;
51
52 fn close(&mut self);
54}
55
56#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)]
58pub enum Error {
59 BufferTooSmall,
63 BufferTooLarge,
65 InvalidState,
67 PermissionDenied,
69 NoRoute,
71 InvalidPort,
73 InvalidAddress,
77 NetworkDown,
79 SocketNotBound,
81 Other,
84}
85
86impl Display for Error {
87 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
88 match self {
89 Error::InvalidState => {
90 write!(f, "The socket is in an invalid state.")
91 }
92 Error::BufferTooSmall => {
93 write!(
94 f,
95 "The provided buffer was too small for the received datagram."
96 )
97 }
98 Error::BufferTooLarge => {
99 write!(f, "The provided buffer was too large for internal buffer.")
100 }
101 Error::NoRoute => {
102 write!(f, "No route to host.")
103 }
104 Error::PermissionDenied => {
105 write!(f, "No permission to access the resource.")
106 }
107 Error::InvalidPort => {
108 write!(f, "The provided port is invalid.")
109 }
110 Error::InvalidAddress => {
111 write!(f, "The provided address is invalid.")
112 }
113 Error::NetworkDown => {
114 write!(f, "The network stack is down.")
115 }
116 Error::Other => {
117 write!(
118 f,
119 "Unspecified error, please open a bug report if you encounter this error."
120 )
121 }
122 Error::SocketNotBound => {
123 write!(
124 f,
125 "The socket is not bound to an outgoing address and port."
126 )
127 }
128 }
129 }
130}
131
132impl core::error::Error for Error {}
133
134#[doc(hidden)]
135#[cfg(feature = "test-suites")]
136#[cfg_attr(coverage_nightly, coverage(off))]
137pub mod test_suite {
138 use crate::net::udp::{Error, UdpSocket};
141 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
142
143 pub async fn test_bind_all_zero_address_v4(mut socket: impl UdpSocket) {
144 let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);
145
146 socket.bind(address).await.unwrap();
147
148 let bound_addr = socket.local_addr().unwrap();
149
150 assert_eq!(bound_addr.ip(), IpAddr::V4(std::net::Ipv4Addr::UNSPECIFIED));
151
152 assert_ne!(
153 bound_addr.port(),
154 0,
155 "port should be automatically assigned"
156 );
157
158 socket.close();
159 }
160
161 pub async fn test_bind_all_zero_address_v6(mut socket: impl UdpSocket) {
162 let address = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), 0);
163
164 socket.bind(address).await.unwrap();
165
166 let bound_addr = socket.local_addr().unwrap();
167
168 assert_eq!(bound_addr.ip(), IpAddr::V6(std::net::Ipv6Addr::UNSPECIFIED));
169
170 assert_ne!(
171 bound_addr.port(),
172 0,
173 "port should be automatically assigned"
174 );
175
176 socket.close();
177 }
178
179 pub async fn test_bind_specific_port(mut socket: impl UdpSocket, ip_address: &str) {
180 let ip_address = ip_address.parse().unwrap();
181 let address = SocketAddr::new(ip_address, 58080);
182
183 socket.bind(address).await.unwrap();
184
185 let bound_addr = socket.local_addr().unwrap();
186
187 assert_eq!(bound_addr.ip(), ip_address);
188 assert_eq!(bound_addr.port(), 58080, "port should match requested port");
189
190 socket.close();
191 }
192
193 pub async fn test_send_recv(
194 mut socket1: impl UdpSocket,
195 mut socket2: impl UdpSocket,
196 ip_address: &str,
197 ) {
198 let ip_address = ip_address.parse().unwrap();
199 let addr1 = SocketAddr::new(ip_address, 58081);
200 let addr2 = SocketAddr::new(ip_address, 58082);
201
202 socket1.bind(addr1).await.unwrap();
203 socket2.bind(addr2).await.unwrap();
204
205 let send_data = b"Hello, UDP!";
206 let mut recv_buffer = [0u8; 64];
207
208 let sent = socket1.send_to(send_data, addr2).await.unwrap();
209 assert_eq!(sent, send_data.len());
210
211 let (received, sender_addr) = socket2.recv_from(&mut recv_buffer).await.unwrap();
212 assert_eq!(received, send_data.len());
213 assert_eq!(&recv_buffer[..received], send_data);
214 assert_eq!(sender_addr, addr1);
215
216 let response = b"Hello back!";
217 let sent = socket2.send_to(response, addr1).await.unwrap();
218 assert_eq!(sent, response.len());
219
220 let (received, sender_addr) = socket1.recv_from(&mut recv_buffer).await.unwrap();
221 assert_eq!(received, response.len());
222 assert_eq!(&recv_buffer[..received], response);
223 assert_eq!(sender_addr, addr2);
224
225 socket1.close();
226 socket2.close();
227 }
228
229 pub async fn test_local_addr_before_bind(socket: impl UdpSocket) {
230 assert_eq!(socket.local_addr(), Err(Error::SocketNotBound));
231 }
232
233 pub async fn test_close_socket(mut socket: impl UdpSocket, ip_address: &str) {
234 let ip_address = ip_address.parse().unwrap();
235 let address = SocketAddr::new(ip_address, 58085);
236
237 socket.bind(address).await.unwrap();
238 let bound_addr = socket.local_addr().unwrap();
239 assert_eq!(bound_addr, address);
240
241 socket.close();
242
243 assert_eq!(socket.local_addr(), Err(Error::SocketNotBound));
244 }
245
246 pub async fn test_recv_without_bind(socket: impl UdpSocket) {
247 let mut buffer = [0u8; 64];
248 assert_eq!(
249 socket.recv_from(&mut buffer).await,
250 Err(Error::SocketNotBound)
251 );
252 }
253
254 pub async fn test_send_without_bind(socket: impl UdpSocket, ip_address: &str) {
255 let ip_address = ip_address.parse().unwrap();
256 let target_addr = SocketAddr::new(ip_address, 58086);
257 let data = b"test data";
258
259 assert_eq!(
260 socket.send_to(data, target_addr).await,
261 Err(Error::SocketNotBound)
262 );
263 }
264
265 pub async fn test_bind_multiple_sockets_same_ip(
266 mut socket1: impl UdpSocket,
267 mut socket2: impl UdpSocket,
268 ip_address: &str,
269 ) {
270 let ip_address = ip_address.parse().unwrap();
271 let address = SocketAddr::new(ip_address, 58087);
272
273 socket1.bind(address).await.unwrap();
274 socket2.bind(address).await.unwrap();
275 }
276
277 pub async fn test_zero_length_datagram(
278 mut socket1: impl UdpSocket,
279 mut socket2: impl UdpSocket,
280 ip_address: &str,
281 ) {
282 let ip_address = ip_address.parse().unwrap();
283 let addr1 = SocketAddr::new(ip_address, 58088);
284 let addr2 = SocketAddr::new(ip_address, 58089);
285
286 socket1.bind(addr1).await.unwrap();
287 socket2.bind(addr2).await.unwrap();
288
289 let empty_data = &[];
290 let sent = socket1.send_to(empty_data, addr2).await.unwrap();
291 assert_eq!(sent, 0);
292
293 let mut recv_buffer = [0u8; 64];
294 let (received, sender_addr) = socket2.recv_from(&mut recv_buffer).await.unwrap();
295 assert_eq!(received, 0);
296 assert_eq!(sender_addr, addr1);
297
298 socket1.close();
299 socket2.close();
300 }
301
302 pub async fn test_max_datagram_size(
303 mut socket1: impl UdpSocket,
304 mut socket2: impl UdpSocket,
305 ip_address: &str,
306 ) {
307 let ip_address = ip_address.parse().unwrap();
308 let addr1 = SocketAddr::new(ip_address, 58090);
309 let addr2 = SocketAddr::new(ip_address, 58091);
310
311 socket1.bind(addr1).await.unwrap();
312 socket2.bind(addr2).await.unwrap();
313
314 const MAX_SIZE: usize = 65507;
317 let mut send_data = [0u8; MAX_SIZE];
318 for (i, byte) in send_data.iter_mut().enumerate() {
319 *byte = (i % 256) as u8;
320 }
321
322 let sent = socket1.send_to(&send_data, addr2).await.unwrap();
323 assert_eq!(sent, MAX_SIZE);
324
325 let mut recv_buffer = [0u8; MAX_SIZE];
326 let (received, sender_addr) = socket2.recv_from(&mut recv_buffer).await.unwrap();
327 assert_eq!(received, MAX_SIZE);
328 assert_eq!(&recv_buffer[..], &send_data[..]);
329 assert_eq!(sender_addr, addr1);
330
331 socket1.close();
332 socket2.close();
333 }
334
335 pub async fn test_multiple_binds(mut socket: impl UdpSocket, ip_address: &str) {
336 let ip_address = ip_address.parse().unwrap();
337 let addr1 = SocketAddr::new(ip_address, 58092);
338 let addr2 = SocketAddr::new(ip_address, 58093);
339
340 socket.bind(addr1).await.unwrap();
341 assert_eq!(socket.local_addr().unwrap(), addr1);
342
343 assert_eq!(socket.bind(addr2).await, Err(Error::InvalidState));
344
345 socket.close();
346 }
347
348 pub async fn test_rebind_after_close(mut socket: impl UdpSocket, ip_address: &str) {
349 let ip_address = ip_address.parse().unwrap();
350 let addr1 = SocketAddr::new(ip_address, 58094);
351 let addr2 = SocketAddr::new(ip_address, 58095);
352
353 socket.bind(addr1).await.unwrap();
354 assert_eq!(socket.local_addr().unwrap(), addr1);
355
356 socket.close();
357
358 assert_eq!(socket.local_addr(), Err(Error::SocketNotBound));
359
360 socket.bind(addr2).await.unwrap();
361 assert_eq!(socket.local_addr().unwrap(), addr2);
362
363 socket.close();
364 }
365}