nex_socket/udp/
async_impl.rs1use crate::udp::UdpConfig;
2use socket2::{Domain, Protocol, Socket, Type as SockType};
3use std::io;
4use std::net::{SocketAddr, UdpSocket as StdUdpSocket};
5use tokio::net::UdpSocket;
6
7#[derive(Debug)]
9pub struct AsyncUdpSocket {
10 socket: Socket,
11}
12
13impl AsyncUdpSocket {
14 pub fn from_config(config: &UdpConfig) -> io::Result<Self> {
16 let domain = match config.bind_addr {
18 Some(SocketAddr::V4(_)) => Domain::IPV4,
19 Some(SocketAddr::V6(_)) => Domain::IPV6,
20 None => Domain::IPV4, };
22
23 let socket = Socket::new(domain, SockType::DGRAM, Some(Protocol::UDP))?;
24
25 if let Some(flag) = config.reuseaddr {
26 socket.set_reuse_address(flag)?;
27 }
28
29 if let Some(flag) = config.broadcast {
30 socket.set_broadcast(flag)?;
31 }
32
33 if let Some(ttl) = config.ttl {
34 socket.set_ttl(ttl)?;
35 }
36
37 #[cfg(any(target_os = "linux", target_os = "android", target_os = "fuchsia"))]
38 if let Some(iface) = &config.bind_device {
39 socket.bind_device(Some(iface.as_bytes()))?;
40 }
41
42 if let Some(addr) = config.bind_addr {
43 socket.bind(&addr.into())?;
44 }
45
46 socket.set_nonblocking(true)?;
47
48 Ok(Self { socket })
49 }
50
51 pub fn new(domain: Domain, sock_type: SockType) -> io::Result<Self> {
53 let socket = Socket::new(domain, sock_type, Some(Protocol::UDP))?;
54 socket.set_nonblocking(true)?;
55 Ok(Self { socket })
56 }
57
58 pub fn v4_dgram() -> io::Result<Self> {
60 Self::new(Domain::IPV4, SockType::DGRAM)
61 }
62
63 pub fn v6_dgram() -> io::Result<Self> {
65 Self::new(Domain::IPV6, SockType::DGRAM)
66 }
67
68 pub fn raw_v4() -> io::Result<Self> {
70 Self::new(Domain::IPV4, SockType::RAW)
71 }
72
73 pub fn raw_v6() -> io::Result<Self> {
75 Self::new(Domain::IPV6, SockType::RAW)
76 }
77
78 pub async fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> {
80 let std_udp: StdUdpSocket = self.socket.try_clone()?.into();
81 let udp_socket = UdpSocket::from_std(std_udp)?;
82 udp_socket.send_to(buf, target).await
83 }
84
85 pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
87 let std_udp: StdUdpSocket = self.socket.try_clone()?.into();
88 let udp_socket = UdpSocket::from_std(std_udp)?;
89 udp_socket.recv_from(buf).await
90 }
91
92 pub fn local_addr(&self) -> io::Result<SocketAddr> {
94 self.socket.local_addr()?.as_socket().ok_or_else(|| {
95 io::Error::new(io::ErrorKind::Other, "Failed to get socket address")
96 })
97 }
98
99 pub fn into_tokio_socket(self) -> io::Result<UdpSocket> {
100 let std_socket: StdUdpSocket = self.socket.into();
101 UdpSocket::from_std(std_socket)
102 }
103
104 #[cfg(unix)]
105 pub fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
106 use std::os::fd::AsRawFd;
107 self.socket.as_raw_fd()
108 }
109
110 #[cfg(windows)]
111 pub fn as_raw_socket(&self) -> std::os::windows::io::RawSocket {
112 use std::os::windows::io::AsRawSocket;
113 self.socket.as_raw_socket()
114 }
115}