diff options
Diffstat (limited to 'vendor/socket2/src/sockaddr.rs')
| -rw-r--r-- | vendor/socket2/src/sockaddr.rs | 575 |
1 files changed, 0 insertions, 575 deletions
diff --git a/vendor/socket2/src/sockaddr.rs b/vendor/socket2/src/sockaddr.rs deleted file mode 100644 index c80dccf3..00000000 --- a/vendor/socket2/src/sockaddr.rs +++ /dev/null @@ -1,575 +0,0 @@ -use std::hash::Hash; -use std::mem::{self, size_of, MaybeUninit}; -use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; -use std::path::Path; -use std::{fmt, io, ptr}; - -#[cfg(windows)] -use windows_sys::Win32::Networking::WinSock::SOCKADDR_IN6_0; - -use crate::sys::{ - c_int, sa_family_t, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_storage, socklen_t, AF_INET, - AF_INET6, AF_UNIX, -}; -use crate::Domain; - -/// The address of a socket. -/// -/// `SockAddr`s may be constructed directly to and from the standard library -/// [`SocketAddr`], [`SocketAddrV4`], and [`SocketAddrV6`] types. -#[derive(Clone)] -pub struct SockAddr { - storage: sockaddr_storage, - len: socklen_t, -} - -#[allow(clippy::len_without_is_empty)] -impl SockAddr { - /// Create a `SockAddr` from the underlying storage and its length. - /// - /// # Safety - /// - /// Caller must ensure that the address family and length match the type of - /// storage address. For example if `storage.ss_family` is set to `AF_INET` - /// the `storage` must be initialised as `sockaddr_in`, setting the content - /// and length appropriately. - /// - /// # Examples - /// - /// ``` - /// # fn main() -> std::io::Result<()> { - /// # #[cfg(unix)] { - /// use std::io; - /// use std::mem; - /// use std::os::unix::io::AsRawFd; - /// - /// use socket2::{SockAddr, Socket, Domain, Type}; - /// - /// let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?; - /// - /// // Initialise a `SocketAddr` byte calling `getsockname(2)`. - /// let mut addr_storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; - /// let mut len = mem::size_of_val(&addr_storage) as libc::socklen_t; - /// - /// // The `getsockname(2)` system call will intiliase `storage` for - /// // us, setting `len` to the correct length. - /// let res = unsafe { - /// libc::getsockname( - /// socket.as_raw_fd(), - /// (&mut addr_storage as *mut libc::sockaddr_storage).cast(), - /// &mut len, - /// ) - /// }; - /// if res == -1 { - /// return Err(io::Error::last_os_error()); - /// } - /// - /// let address = unsafe { SockAddr::new(addr_storage, len) }; - /// # drop(address); - /// # } - /// # Ok(()) - /// # } - /// ``` - pub const unsafe fn new(storage: sockaddr_storage, len: socklen_t) -> SockAddr { - SockAddr { storage, len } - } - - /// Initialise a `SockAddr` by calling the function `init`. - /// - /// The type of the address storage and length passed to the function `init` - /// is OS/architecture specific. - /// - /// The address is zeroed before `init` is called and is thus valid to - /// dereference and read from. The length initialised to the maximum length - /// of the storage. - /// - /// # Safety - /// - /// Caller must ensure that the address family and length match the type of - /// storage address. For example if `storage.ss_family` is set to `AF_INET` - /// the `storage` must be initialised as `sockaddr_in`, setting the content - /// and length appropriately. - /// - /// # Examples - /// - /// ``` - /// # fn main() -> std::io::Result<()> { - /// # #[cfg(unix)] { - /// use std::io; - /// use std::os::unix::io::AsRawFd; - /// - /// use socket2::{SockAddr, Socket, Domain, Type}; - /// - /// let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?; - /// - /// // Initialise a `SocketAddr` byte calling `getsockname(2)`. - /// let (_, address) = unsafe { - /// SockAddr::try_init(|addr_storage, len| { - /// // The `getsockname(2)` system call will intiliase `storage` for - /// // us, setting `len` to the correct length. - /// if libc::getsockname(socket.as_raw_fd(), addr_storage.cast(), len) == -1 { - /// Err(io::Error::last_os_error()) - /// } else { - /// Ok(()) - /// } - /// }) - /// }?; - /// # drop(address); - /// # } - /// # Ok(()) - /// # } - /// ``` - pub unsafe fn try_init<F, T>(init: F) -> io::Result<(T, SockAddr)> - where - F: FnOnce(*mut sockaddr_storage, *mut socklen_t) -> io::Result<T>, - { - const STORAGE_SIZE: socklen_t = size_of::<sockaddr_storage>() as socklen_t; - // NOTE: `SockAddr::unix` depends on the storage being zeroed before - // calling `init`. - // NOTE: calling `recvfrom` with an empty buffer also depends on the - // storage being zeroed before calling `init` as the OS might not - // initialise it. - let mut storage = MaybeUninit::<sockaddr_storage>::zeroed(); - let mut len = STORAGE_SIZE; - init(storage.as_mut_ptr(), &mut len).map(|res| { - debug_assert!(len <= STORAGE_SIZE, "overflown address storage"); - let addr = SockAddr { - // Safety: zeroed-out `sockaddr_storage` is valid, caller must - // ensure at least `len` bytes are valid. - storage: storage.assume_init(), - len, - }; - (res, addr) - }) - } - - /// Constructs a `SockAddr` with the family `AF_UNIX` and the provided path. - /// - /// Returns an error if the path is longer than `SUN_LEN`. - pub fn unix<P>(path: P) -> io::Result<SockAddr> - where - P: AsRef<Path>, - { - crate::sys::unix_sockaddr(path.as_ref()) - } - - /// Set the length of the address. - /// - /// # Safety - /// - /// Caller must ensure that the address up to `length` bytes are properly - /// initialised. - pub unsafe fn set_length(&mut self, length: socklen_t) { - self.len = length; - } - - /// Returns this address's family. - pub const fn family(&self) -> sa_family_t { - self.storage.ss_family - } - - /// Returns this address's `Domain`. - pub const fn domain(&self) -> Domain { - Domain(self.storage.ss_family as c_int) - } - - /// Returns the size of this address in bytes. - pub const fn len(&self) -> socklen_t { - self.len - } - - /// Returns a raw pointer to the address. - pub const fn as_ptr(&self) -> *const sockaddr { - ptr::addr_of!(self.storage).cast() - } - - /// Retuns the address as the storage. - pub const fn as_storage(self) -> sockaddr_storage { - self.storage - } - - /// Returns true if this address is in the `AF_INET` (IPv4) family, false otherwise. - pub const fn is_ipv4(&self) -> bool { - self.storage.ss_family == AF_INET as sa_family_t - } - - /// Returns true if this address is in the `AF_INET6` (IPv6) family, false - /// otherwise. - pub const fn is_ipv6(&self) -> bool { - self.storage.ss_family == AF_INET6 as sa_family_t - } - - /// Returns true if this address is of a unix socket (for local interprocess communication), - /// i.e. it is from the `AF_UNIX` family, false otherwise. - pub fn is_unix(&self) -> bool { - self.storage.ss_family == AF_UNIX as sa_family_t - } - - /// Returns this address as a `SocketAddr` if it is in the `AF_INET` (IPv4) - /// or `AF_INET6` (IPv6) family, otherwise returns `None`. - pub fn as_socket(&self) -> Option<SocketAddr> { - if self.storage.ss_family == AF_INET as sa_family_t { - // SAFETY: if the `ss_family` field is `AF_INET` then storage must - // be a `sockaddr_in`. - let addr = unsafe { &*(ptr::addr_of!(self.storage).cast::<sockaddr_in>()) }; - let ip = crate::sys::from_in_addr(addr.sin_addr); - let port = u16::from_be(addr.sin_port); - Some(SocketAddr::V4(SocketAddrV4::new(ip, port))) - } else if self.storage.ss_family == AF_INET6 as sa_family_t { - // SAFETY: if the `ss_family` field is `AF_INET6` then storage must - // be a `sockaddr_in6`. - let addr = unsafe { &*(ptr::addr_of!(self.storage).cast::<sockaddr_in6>()) }; - let ip = crate::sys::from_in6_addr(addr.sin6_addr); - let port = u16::from_be(addr.sin6_port); - Some(SocketAddr::V6(SocketAddrV6::new( - ip, - port, - addr.sin6_flowinfo, - #[cfg(unix)] - addr.sin6_scope_id, - #[cfg(windows)] - unsafe { - addr.Anonymous.sin6_scope_id - }, - ))) - } else { - None - } - } - - /// Returns this address as a [`SocketAddrV4`] if it is in the `AF_INET` - /// family. - pub fn as_socket_ipv4(&self) -> Option<SocketAddrV4> { - match self.as_socket() { - Some(SocketAddr::V4(addr)) => Some(addr), - _ => None, - } - } - - /// Returns this address as a [`SocketAddrV6`] if it is in the `AF_INET6` - /// family. - pub fn as_socket_ipv6(&self) -> Option<SocketAddrV6> { - match self.as_socket() { - Some(SocketAddr::V6(addr)) => Some(addr), - _ => None, - } - } - - /// Returns the initialised storage bytes. - fn as_bytes(&self) -> &[u8] { - // SAFETY: `self.storage` is a C struct which can always be treated a - // slice of bytes. Furthermore, we ensure we don't read any unitialised - // bytes by using `self.len`. - unsafe { std::slice::from_raw_parts(self.as_ptr().cast(), self.len as usize) } - } -} - -impl From<SocketAddr> for SockAddr { - fn from(addr: SocketAddr) -> SockAddr { - match addr { - SocketAddr::V4(addr) => addr.into(), - SocketAddr::V6(addr) => addr.into(), - } - } -} - -impl From<SocketAddrV4> for SockAddr { - fn from(addr: SocketAddrV4) -> SockAddr { - // SAFETY: a `sockaddr_storage` of all zeros is valid. - let mut storage = unsafe { mem::zeroed::<sockaddr_storage>() }; - let len = { - let storage = unsafe { &mut *ptr::addr_of_mut!(storage).cast::<sockaddr_in>() }; - storage.sin_family = AF_INET as sa_family_t; - storage.sin_port = addr.port().to_be(); - storage.sin_addr = crate::sys::to_in_addr(addr.ip()); - storage.sin_zero = Default::default(); - mem::size_of::<sockaddr_in>() as socklen_t - }; - #[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "haiku", - target_os = "hermit", - target_os = "ios", - target_os = "visionos", - target_os = "macos", - target_os = "netbsd", - target_os = "nto", - target_os = "openbsd", - target_os = "tvos", - target_os = "vxworks", - target_os = "watchos", - ))] - { - storage.ss_len = len as u8; - } - SockAddr { storage, len } - } -} - -impl From<SocketAddrV6> for SockAddr { - fn from(addr: SocketAddrV6) -> SockAddr { - // SAFETY: a `sockaddr_storage` of all zeros is valid. - let mut storage = unsafe { mem::zeroed::<sockaddr_storage>() }; - let len = { - let storage = unsafe { &mut *ptr::addr_of_mut!(storage).cast::<sockaddr_in6>() }; - storage.sin6_family = AF_INET6 as sa_family_t; - storage.sin6_port = addr.port().to_be(); - storage.sin6_addr = crate::sys::to_in6_addr(addr.ip()); - storage.sin6_flowinfo = addr.flowinfo(); - #[cfg(unix)] - { - storage.sin6_scope_id = addr.scope_id(); - } - #[cfg(windows)] - { - storage.Anonymous = SOCKADDR_IN6_0 { - sin6_scope_id: addr.scope_id(), - }; - } - mem::size_of::<sockaddr_in6>() as socklen_t - }; - #[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "haiku", - target_os = "hermit", - target_os = "ios", - target_os = "visionos", - target_os = "macos", - target_os = "netbsd", - target_os = "nto", - target_os = "openbsd", - target_os = "tvos", - target_os = "vxworks", - target_os = "watchos", - ))] - { - storage.ss_len = len as u8; - } - SockAddr { storage, len } - } -} - -impl fmt::Debug for SockAddr { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut f = fmt.debug_struct("SockAddr"); - #[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "haiku", - target_os = "hermit", - target_os = "ios", - target_os = "visionos", - target_os = "macos", - target_os = "netbsd", - target_os = "nto", - target_os = "openbsd", - target_os = "tvos", - target_os = "vxworks", - target_os = "watchos", - ))] - f.field("ss_len", &self.storage.ss_len); - f.field("ss_family", &self.storage.ss_family) - .field("len", &self.len) - .finish() - } -} - -impl PartialEq for SockAddr { - fn eq(&self, other: &Self) -> bool { - self.as_bytes() == other.as_bytes() - } -} - -impl Eq for SockAddr {} - -impl Hash for SockAddr { - fn hash<H: std::hash::Hasher>(&self, state: &mut H) { - self.as_bytes().hash(state); - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn ipv4() { - use std::net::Ipv4Addr; - let std = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876); - let addr = SockAddr::from(std); - assert!(addr.is_ipv4()); - assert!(!addr.is_ipv6()); - assert!(!addr.is_unix()); - assert_eq!(addr.family(), AF_INET as sa_family_t); - assert_eq!(addr.domain(), Domain::IPV4); - assert_eq!(addr.len(), size_of::<sockaddr_in>() as socklen_t); - assert_eq!(addr.as_socket(), Some(SocketAddr::V4(std))); - assert_eq!(addr.as_socket_ipv4(), Some(std)); - assert!(addr.as_socket_ipv6().is_none()); - - let addr = SockAddr::from(SocketAddr::from(std)); - assert_eq!(addr.family(), AF_INET as sa_family_t); - assert_eq!(addr.len(), size_of::<sockaddr_in>() as socklen_t); - assert_eq!(addr.as_socket(), Some(SocketAddr::V4(std))); - assert_eq!(addr.as_socket_ipv4(), Some(std)); - assert!(addr.as_socket_ipv6().is_none()); - #[cfg(unix)] - { - assert!(addr.as_pathname().is_none()); - assert!(addr.as_abstract_namespace().is_none()); - } - } - - #[test] - fn ipv6() { - use std::net::Ipv6Addr; - let std = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12); - let addr = SockAddr::from(std); - assert!(addr.is_ipv6()); - assert!(!addr.is_ipv4()); - assert!(!addr.is_unix()); - assert_eq!(addr.family(), AF_INET6 as sa_family_t); - assert_eq!(addr.domain(), Domain::IPV6); - assert_eq!(addr.len(), size_of::<sockaddr_in6>() as socklen_t); - assert_eq!(addr.as_socket(), Some(SocketAddr::V6(std))); - assert!(addr.as_socket_ipv4().is_none()); - assert_eq!(addr.as_socket_ipv6(), Some(std)); - - let addr = SockAddr::from(SocketAddr::from(std)); - assert_eq!(addr.family(), AF_INET6 as sa_family_t); - assert_eq!(addr.len(), size_of::<sockaddr_in6>() as socklen_t); - assert_eq!(addr.as_socket(), Some(SocketAddr::V6(std))); - assert!(addr.as_socket_ipv4().is_none()); - assert_eq!(addr.as_socket_ipv6(), Some(std)); - #[cfg(unix)] - { - assert!(addr.as_pathname().is_none()); - assert!(addr.as_abstract_namespace().is_none()); - } - } - - #[test] - fn ipv4_eq() { - use std::net::Ipv4Addr; - - let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876); - let std2 = SocketAddrV4::new(Ipv4Addr::new(5, 6, 7, 8), 8765); - - test_eq( - SockAddr::from(std1), - SockAddr::from(std1), - SockAddr::from(std2), - ); - } - - #[test] - fn ipv4_hash() { - use std::net::Ipv4Addr; - - let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876); - let std2 = SocketAddrV4::new(Ipv4Addr::new(5, 6, 7, 8), 8765); - - test_hash( - SockAddr::from(std1), - SockAddr::from(std1), - SockAddr::from(std2), - ); - } - - #[test] - fn ipv6_eq() { - use std::net::Ipv6Addr; - - let std1 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12); - let std2 = SocketAddrV6::new(Ipv6Addr::new(3, 4, 5, 6, 7, 8, 9, 0), 7654, 13, 14); - - test_eq( - SockAddr::from(std1), - SockAddr::from(std1), - SockAddr::from(std2), - ); - } - - #[test] - fn ipv6_hash() { - use std::net::Ipv6Addr; - - let std1 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12); - let std2 = SocketAddrV6::new(Ipv6Addr::new(3, 4, 5, 6, 7, 8, 9, 0), 7654, 13, 14); - - test_hash( - SockAddr::from(std1), - SockAddr::from(std1), - SockAddr::from(std2), - ); - } - - #[test] - fn ipv4_ipv6_eq() { - use std::net::Ipv4Addr; - use std::net::Ipv6Addr; - - let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876); - let std2 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12); - - test_eq( - SockAddr::from(std1), - SockAddr::from(std1), - SockAddr::from(std2), - ); - - test_eq( - SockAddr::from(std2), - SockAddr::from(std2), - SockAddr::from(std1), - ); - } - - #[test] - fn ipv4_ipv6_hash() { - use std::net::Ipv4Addr; - use std::net::Ipv6Addr; - - let std1 = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876); - let std2 = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12); - - test_hash( - SockAddr::from(std1), - SockAddr::from(std1), - SockAddr::from(std2), - ); - - test_hash( - SockAddr::from(std2), - SockAddr::from(std2), - SockAddr::from(std1), - ); - } - - #[allow(clippy::eq_op)] // allow a0 == a0 check - fn test_eq(a0: SockAddr, a1: SockAddr, b: SockAddr) { - assert!(a0 == a0); - assert!(a0 == a1); - assert!(a1 == a0); - assert!(a0 != b); - assert!(b != a0); - } - - fn test_hash(a0: SockAddr, a1: SockAddr, b: SockAddr) { - assert!(calculate_hash(&a0) == calculate_hash(&a0)); - assert!(calculate_hash(&a0) == calculate_hash(&a1)); - // technically unequal values can have the same hash, in this case x != z and both have different hashes - assert!(calculate_hash(&a0) != calculate_hash(&b)); - } - - fn calculate_hash(x: &SockAddr) -> u64 { - use std::collections::hash_map::DefaultHasher; - use std::hash::Hasher; - - let mut hasher = DefaultHasher::new(); - x.hash(&mut hasher); - hasher.finish() - } -} |
