nex_socket/udp/
sync_impl.rs1use crate::udp::UdpConfig;
2use socket2::{Domain, Protocol, Socket, Type as SockType};
3use std::io;
4use std::net::{SocketAddr, UdpSocket as StdUdpSocket};
5
6#[derive(Debug)]
8pub struct UdpSocket {
9 socket: Socket,
10}
11
12impl UdpSocket {
13 pub fn from_config(config: &UdpConfig) -> io::Result<Self> {
15 let domain = match config.bind_addr {
17 Some(SocketAddr::V4(_)) => Domain::IPV4,
18 Some(SocketAddr::V6(_)) => Domain::IPV6,
19 None => Domain::IPV4, };
21
22 let socket = Socket::new(domain, SockType::DGRAM, Some(Protocol::UDP))?;
23
24 if let Some(flag) = config.reuseaddr {
25 socket.set_reuse_address(flag)?;
26 }
27
28 if let Some(flag) = config.broadcast {
29 socket.set_broadcast(flag)?;
30 }
31
32 if let Some(ttl) = config.ttl {
33 socket.set_ttl(ttl)?;
34 }
35
36 #[cfg(any(target_os = "linux", target_os = "android", target_os = "fuchsia"))]
37 if let Some(iface) = &config.bind_device {
38 socket.bind_device(Some(iface.as_bytes()))?;
39 }
40
41 if let Some(addr) = config.bind_addr {
42 socket.bind(&addr.into())?;
43 }
44
45 socket.set_nonblocking(false)?; Ok(Self { socket })
47 }
48
49 pub fn new(domain: Domain, sock_type: SockType) -> io::Result<Self> {
51 let socket = Socket::new(domain, sock_type, Some(Protocol::UDP))?;
52 socket.set_nonblocking(false)?;
53 Ok(Self { socket })
54 }
55
56 pub fn v4_dgram() -> io::Result<Self> {
58 Self::new(Domain::IPV4, SockType::DGRAM)
59 }
60
61 pub fn v6_dgram() -> io::Result<Self> {
63 Self::new(Domain::IPV6, SockType::DGRAM)
64 }
65
66 pub fn raw_v4() -> io::Result<Self> {
68 Self::new(Domain::IPV4, SockType::RAW)
69 }
70
71 pub fn raw_v6() -> io::Result<Self> {
73 Self::new(Domain::IPV6, SockType::RAW)
74 }
75
76 pub fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> {
78 self.socket.send_to(buf, &target.into())
79 }
80
81 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
83 let buf_maybe = unsafe {
85 std::slice::from_raw_parts_mut(
86 buf.as_mut_ptr() as *mut std::mem::MaybeUninit<u8>,
87 buf.len(),
88 )
89 };
90
91 let (n, addr) = self.socket.recv_from(buf_maybe)?;
92 let addr = addr
93 .as_socket()
94 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "invalid address format"))?;
95
96 Ok((n, addr))
97 }
98
99 pub fn local_addr(&self) -> io::Result<SocketAddr> {
101 self.socket
102 .local_addr()?
103 .as_socket()
104 .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Failed to get socket address"))
105 }
106
107 pub fn to_std(self) -> io::Result<StdUdpSocket> {
109 Ok(self.socket.into())
110 }
111
112 #[cfg(unix)]
113 pub fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
114 use std::os::fd::AsRawFd;
115 self.socket.as_raw_fd()
116 }
117
118 #[cfg(windows)]
119 pub fn as_raw_socket(&self) -> std::os::windows::io::RawSocket {
120 use std::os::windows::io::AsRawSocket;
121 self.socket.as_raw_socket()
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128
129 #[test]
130 fn create_v4_socket() {
131 let sock = UdpSocket::v4_dgram().expect("create socket");
132 let addr = sock.local_addr().expect("addr");
133 assert!(addr.is_ipv4());
134 }
135}