Skip to main content

nex_socket/udp/
mod.rs

1//! UDP socket.
2//!
3//! Provides synchronous and asynchronous UDP APIs along with
4//! configuration utilities for common socket options.
5mod async_impl;
6mod config;
7mod sync_impl;
8
9use std::io;
10
11use socket2::Socket;
12
13use crate::SocketFamily;
14
15#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
16fn set_bool_sockopt(
17    socket: &Socket,
18    level: libc::c_int,
19    optname: libc::c_int,
20    on: bool,
21) -> io::Result<()> {
22    use std::os::fd::AsRawFd;
23    let value: libc::c_int = if on { 1 } else { 0 };
24    let ret = unsafe {
25        libc::setsockopt(
26            socket.as_raw_fd(),
27            level,
28            optname,
29            (&value as *const libc::c_int).cast(),
30            std::mem::size_of::<libc::c_int>() as libc::socklen_t,
31        )
32    };
33    if ret == 0 {
34        Ok(())
35    } else {
36        Err(io::Error::last_os_error())
37    }
38}
39
40#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
41fn get_bool_sockopt(socket: &Socket, level: libc::c_int, optname: libc::c_int) -> io::Result<bool> {
42    use std::os::fd::AsRawFd;
43    let mut value: libc::c_int = 0;
44    let mut len = std::mem::size_of::<libc::c_int>() as libc::socklen_t;
45    let ret = unsafe {
46        libc::getsockopt(
47            socket.as_raw_fd(),
48            level,
49            optname,
50            (&mut value as *mut libc::c_int).cast(),
51            &mut len,
52        )
53    };
54    if ret == 0 {
55        Ok(value != 0)
56    } else {
57        Err(io::Error::last_os_error())
58    }
59}
60
61pub(crate) fn set_recv_pktinfo(socket: &Socket, family: SocketFamily, on: bool) -> io::Result<()> {
62    match family {
63        SocketFamily::IPV4 => set_recv_pktinfo_v4(socket, on),
64        SocketFamily::IPV6 => set_recv_pktinfo_v6(socket, on),
65    }
66}
67
68#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
69pub(crate) fn set_recv_pktinfo_v4(socket: &Socket, on: bool) -> io::Result<()> {
70    set_bool_sockopt(socket, libc::IPPROTO_IP, libc::IP_PKTINFO, on)
71}
72
73#[cfg(not(any(target_os = "android", target_os = "fuchsia", target_os = "linux")))]
74pub(crate) fn set_recv_pktinfo_v4(_socket: &Socket, _on: bool) -> io::Result<()> {
75    Err(io::Error::new(
76        io::ErrorKind::Unsupported,
77        "IP_PKTINFO is not supported on this platform",
78    ))
79}
80
81#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
82pub(crate) fn set_recv_pktinfo_v6(socket: &Socket, on: bool) -> io::Result<()> {
83    set_bool_sockopt(socket, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO, on)
84}
85
86#[cfg(not(any(target_os = "android", target_os = "fuchsia", target_os = "linux")))]
87pub(crate) fn set_recv_pktinfo_v6(_socket: &Socket, _on: bool) -> io::Result<()> {
88    Err(io::Error::new(
89        io::ErrorKind::Unsupported,
90        "IPV6_RECVPKTINFO is not supported on this platform",
91    ))
92}
93
94#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
95pub(crate) fn recv_pktinfo_v4(socket: &Socket) -> io::Result<bool> {
96    get_bool_sockopt(socket, libc::IPPROTO_IP, libc::IP_PKTINFO)
97}
98
99#[cfg(not(any(target_os = "android", target_os = "fuchsia", target_os = "linux")))]
100pub(crate) fn recv_pktinfo_v4(_socket: &Socket) -> io::Result<bool> {
101    Err(io::Error::new(
102        io::ErrorKind::Unsupported,
103        "IP_PKTINFO is not supported on this platform",
104    ))
105}
106
107#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
108pub(crate) fn recv_pktinfo_v6(socket: &Socket) -> io::Result<bool> {
109    get_bool_sockopt(socket, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO)
110}
111
112#[cfg(not(any(target_os = "android", target_os = "fuchsia", target_os = "linux")))]
113pub(crate) fn recv_pktinfo_v6(_socket: &Socket) -> io::Result<bool> {
114    Err(io::Error::new(
115        io::ErrorKind::Unsupported,
116        "IPV6_RECVPKTINFO is not supported on this platform",
117    ))
118}
119
120pub use async_impl::*;
121pub use config::*;
122pub use sync_impl::*;