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 #![expect(missing_docs, reason = "tests")]
139 use crate::net::udp::{Error, UdpSocket};
142 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
143
144 pub async fn test_bind_all_zero_address_v4(mut socket: impl UdpSocket) {
145 let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);
146
147 socket.bind(address).await.unwrap();
148
149 let bound_addr = socket.local_addr().unwrap();
150
151 assert_eq!(bound_addr.ip(), IpAddr::V4(std::net::Ipv4Addr::UNSPECIFIED));
152
153 assert_ne!(
154 bound_addr.port(),
155 0,
156 "port should be automatically assigned"
157 );
158
159 socket.close();
160 }
161
162 pub async fn test_bind_all_zero_address_v6(mut socket: impl UdpSocket) {
163 let address = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), 0);
164
165 socket.bind(address).await.unwrap();
166
167 let bound_addr = socket.local_addr().unwrap();
168
169 assert_eq!(bound_addr.ip(), IpAddr::V6(std::net::Ipv6Addr::UNSPECIFIED));
170
171 assert_ne!(
172 bound_addr.port(),
173 0,
174 "port should be automatically assigned"
175 );
176
177 socket.close();
178 }
179
180 pub async fn test_bind_specific_port(mut socket: impl UdpSocket, ip_address: &str) {
181 let ip_address = ip_address.parse().unwrap();
182 let address = SocketAddr::new(ip_address, 58080);
183
184 socket.bind(address).await.unwrap();
185
186 let bound_addr = socket.local_addr().unwrap();
187
188 assert_eq!(bound_addr.ip(), ip_address);
189 assert_eq!(bound_addr.port(), 58080, "port should match requested port");
190
191 socket.close();
192 }
193
194 pub async fn test_send_recv(
195 mut socket1: impl UdpSocket,
196 mut socket2: impl UdpSocket,
197 ip_address: &str,
198 ) {
199 let ip_address = ip_address.parse().unwrap();
200 let addr1 = SocketAddr::new(ip_address, 58081);
201 let addr2 = SocketAddr::new(ip_address, 58082);
202
203 socket1.bind(addr1).await.unwrap();
204 socket2.bind(addr2).await.unwrap();
205
206 let send_data = b"Hello, UDP!";
207 let mut recv_buffer = [0u8; 64];
208
209 let sent = socket1.send_to(send_data, addr2).await.unwrap();
210 assert_eq!(sent, send_data.len());
211
212 let (received, sender_addr) = socket2.recv_from(&mut recv_buffer).await.unwrap();
213 assert_eq!(received, send_data.len());
214 assert_eq!(&recv_buffer[..received], send_data);
215 assert_eq!(sender_addr, addr1);
216
217 let response = b"Hello back!";
218 let sent = socket2.send_to(response, addr1).await.unwrap();
219 assert_eq!(sent, response.len());
220
221 let (received, sender_addr) = socket1.recv_from(&mut recv_buffer).await.unwrap();
222 assert_eq!(received, response.len());
223 assert_eq!(&recv_buffer[..received], response);
224 assert_eq!(sender_addr, addr2);
225
226 socket1.close();
227 socket2.close();
228 }
229
230 pub async fn test_local_addr_before_bind(socket: impl UdpSocket) {
231 assert_eq!(socket.local_addr(), Err(Error::SocketNotBound));
232 }
233
234 pub async fn test_close_socket(mut socket: impl UdpSocket, ip_address: &str) {
235 let ip_address = ip_address.parse().unwrap();
236 let address = SocketAddr::new(ip_address, 58085);
237
238 socket.bind(address).await.unwrap();
239 let bound_addr = socket.local_addr().unwrap();
240 assert_eq!(bound_addr, address);
241
242 socket.close();
243
244 assert_eq!(socket.local_addr(), Err(Error::SocketNotBound));
245 }
246
247 pub async fn test_recv_without_bind(socket: impl UdpSocket) {
248 let mut buffer = [0u8; 64];
249 assert_eq!(
250 socket.recv_from(&mut buffer).await,
251 Err(Error::SocketNotBound)
252 );
253 }
254
255 pub async fn test_send_without_bind(socket: impl UdpSocket, ip_address: &str) {
256 let ip_address = ip_address.parse().unwrap();
257 let target_addr = SocketAddr::new(ip_address, 58086);
258 let data = b"test data";
259
260 assert_eq!(
261 socket.send_to(data, target_addr).await,
262 Err(Error::SocketNotBound)
263 );
264 }
265
266 pub async fn test_bind_multiple_sockets_same_ip(
267 mut socket1: impl UdpSocket,
268 mut socket2: impl UdpSocket,
269 ip_address: &str,
270 ) {
271 let ip_address = ip_address.parse().unwrap();
272 let address = SocketAddr::new(ip_address, 58087);
273
274 socket1.bind(address).await.unwrap();
275 socket2.bind(address).await.unwrap();
276 }
277
278 pub async fn test_zero_length_datagram(
279 mut socket1: impl UdpSocket,
280 mut socket2: impl UdpSocket,
281 ip_address: &str,
282 ) {
283 let ip_address = ip_address.parse().unwrap();
284 let addr1 = SocketAddr::new(ip_address, 58088);
285 let addr2 = SocketAddr::new(ip_address, 58089);
286
287 socket1.bind(addr1).await.unwrap();
288 socket2.bind(addr2).await.unwrap();
289
290 let empty_data = &[];
291 let sent = socket1.send_to(empty_data, addr2).await.unwrap();
292 assert_eq!(sent, 0);
293
294 let mut recv_buffer = [0u8; 64];
295 let (received, sender_addr) = socket2.recv_from(&mut recv_buffer).await.unwrap();
296 assert_eq!(received, 0);
297 assert_eq!(sender_addr, addr1);
298
299 socket1.close();
300 socket2.close();
301 }
302
303 pub async fn test_max_datagram_size(
304 mut socket1: impl UdpSocket,
305 mut socket2: impl UdpSocket,
306 ip_address: &str,
307 ) {
308 let ip_address = ip_address.parse().unwrap();
309 let addr1 = SocketAddr::new(ip_address, 58090);
310 let addr2 = SocketAddr::new(ip_address, 58091);
311
312 socket1.bind(addr1).await.unwrap();
313 socket2.bind(addr2).await.unwrap();
314
315 const MAX_SIZE: usize = 65507;
318 let mut send_data = [0u8; MAX_SIZE];
319 for (i, byte) in send_data.iter_mut().enumerate() {
320 *byte = (i % 256) as u8;
321 }
322
323 let sent = socket1.send_to(&send_data, addr2).await.unwrap();
324 assert_eq!(sent, MAX_SIZE);
325
326 let mut recv_buffer = [0u8; MAX_SIZE];
327 let (received, sender_addr) = socket2.recv_from(&mut recv_buffer).await.unwrap();
328 assert_eq!(received, MAX_SIZE);
329 assert_eq!(&recv_buffer[..], &send_data[..]);
330 assert_eq!(sender_addr, addr1);
331
332 socket1.close();
333 socket2.close();
334 }
335
336 pub async fn test_multiple_binds(mut socket: impl UdpSocket, ip_address: &str) {
337 let ip_address = ip_address.parse().unwrap();
338 let addr1 = SocketAddr::new(ip_address, 58092);
339 let addr2 = SocketAddr::new(ip_address, 58093);
340
341 socket.bind(addr1).await.unwrap();
342 assert_eq!(socket.local_addr().unwrap(), addr1);
343
344 assert_eq!(socket.bind(addr2).await, Err(Error::InvalidState));
345
346 socket.close();
347 }
348
349 pub async fn test_rebind_after_close(mut socket: impl UdpSocket, ip_address: &str) {
350 let ip_address = ip_address.parse().unwrap();
351 let addr1 = SocketAddr::new(ip_address, 58094);
352 let addr2 = SocketAddr::new(ip_address, 58095);
353
354 socket.bind(addr1).await.unwrap();
355 assert_eq!(socket.local_addr().unwrap(), addr1);
356
357 socket.close();
358
359 assert_eq!(socket.local_addr(), Err(Error::SocketNotBound));
360
361 socket.bind(addr2).await.unwrap();
362 assert_eq!(socket.local_addr().unwrap(), addr2);
363
364 socket.close();
365 }
366}