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 inner: UdpSocket,
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 #[cfg(windows)]
49 let std_socket = unsafe {
50 use std::os::windows::io::{FromRawSocket, IntoRawSocket};
51 StdUdpSocket::from_raw_socket(socket.into_raw_socket())
52 };
53 #[cfg(unix)]
54 let std_socket = unsafe {
55 use std::os::fd::{FromRawFd, IntoRawFd};
56 StdUdpSocket::from_raw_fd(socket.into_raw_fd())
57 };
58
59 let inner = UdpSocket::from_std(std_socket)?;
60
61 Ok(Self { inner })
62 }
63
64 pub fn new(domain: Domain, sock_type: SockType) -> io::Result<Self> {
66 let socket = Socket::new(domain, sock_type, Some(Protocol::UDP))?;
67 socket.set_nonblocking(true)?;
68
69 #[cfg(windows)]
70 let std_socket = unsafe {
71 use std::os::windows::io::{FromRawSocket, IntoRawSocket};
72 StdUdpSocket::from_raw_socket(socket.into_raw_socket())
73 };
74 #[cfg(unix)]
75 let std_socket = unsafe {
76 use std::os::fd::{FromRawFd, IntoRawFd};
77 StdUdpSocket::from_raw_fd(socket.into_raw_fd())
78 };
79
80 let inner = UdpSocket::from_std(std_socket)?;
81
82 Ok(Self { inner })
83 }
84
85 pub fn v4_dgram() -> io::Result<Self> {
87 Self::new(Domain::IPV4, SockType::DGRAM)
88 }
89
90 pub fn v6_dgram() -> io::Result<Self> {
92 Self::new(Domain::IPV6, SockType::DGRAM)
93 }
94
95 pub fn raw_v4() -> io::Result<Self> {
97 Self::new(Domain::IPV4, SockType::RAW)
98 }
99
100 pub fn raw_v6() -> io::Result<Self> {
102 Self::new(Domain::IPV6, SockType::RAW)
103 }
104
105 pub async fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> {
107 self.inner.send_to(buf, target).await
108 }
109
110 pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
112 self.inner.recv_from(buf).await
113 }
114
115 pub fn local_addr(&self) -> io::Result<SocketAddr> {
117 self.inner.local_addr()
118 }
119
120 pub fn into_tokio_socket(self) -> io::Result<UdpSocket> {
121 Ok(self.inner)
122 }
123
124 #[cfg(unix)]
125 pub fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
126 use std::os::fd::AsRawFd;
127 self.inner.as_raw_fd()
128 }
129
130 #[cfg(windows)]
131 pub fn as_raw_socket(&self) -> std::os::windows::io::RawSocket {
132 use std::os::windows::io::AsRawSocket;
133 self.inner.as_raw_socket()
134 }
135}