1//! A socket address for any kind of socket.
2//!
3//! This is similar to [`std::net::SocketAddr`], but also supports Unix-domain
4//! socket addresses on Unix.
5//!
6//! # Safety
7//!
8//! The `read` and `write` functions allow decoding and encoding from and to
9//! OS-specific socket address representations in memory.
10#![allow(unsafe_code)]
11
12#[cfg(target_os = "linux")]
13use crate::net::xdp::SocketAddrXdp;
14#[cfg(unix)]
15use crate::net::SocketAddrUnix;
16use crate::net::{AddressFamily, SocketAddr, SocketAddrV4, SocketAddrV6};
17use crate::{backend, io};
18#[cfg(feature = "std")]
19use core::fmt;
20
21pub use backend::net::addr::SocketAddrStorage;
22
23/// `struct sockaddr_storage` as a Rust enum.
24#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
25#[doc(alias = "sockaddr")]
26#[non_exhaustive]
27pub enum SocketAddrAny {
28 /// `struct sockaddr_in`
29 V4(SocketAddrV4),
30 /// `struct sockaddr_in6`
31 V6(SocketAddrV6),
32 /// `struct sockaddr_un`
33 #[cfg(unix)]
34 Unix(SocketAddrUnix),
35 /// `struct sockaddr_xdp`
36 #[cfg(target_os = "linux")]
37 Xdp(SocketAddrXdp),
38}
39
40impl From<SocketAddr> for SocketAddrAny {
41 #[inline]
42 fn from(from: SocketAddr) -> Self {
43 match from {
44 SocketAddr::V4(v4: SocketAddrV4) => Self::V4(v4),
45 SocketAddr::V6(v6: SocketAddrV6) => Self::V6(v6),
46 }
47 }
48}
49
50impl From<SocketAddrV4> for SocketAddrAny {
51 #[inline]
52 fn from(from: SocketAddrV4) -> Self {
53 Self::V4(from)
54 }
55}
56
57impl From<SocketAddrV6> for SocketAddrAny {
58 #[inline]
59 fn from(from: SocketAddrV6) -> Self {
60 Self::V6(from)
61 }
62}
63
64#[cfg(unix)]
65impl From<SocketAddrUnix> for SocketAddrAny {
66 #[inline]
67 fn from(from: SocketAddrUnix) -> Self {
68 Self::Unix(from)
69 }
70}
71
72impl SocketAddrAny {
73 /// Return the address family of this socket address.
74 #[inline]
75 pub const fn address_family(&self) -> AddressFamily {
76 match self {
77 Self::V4(_) => AddressFamily::INET,
78 Self::V6(_) => AddressFamily::INET6,
79 #[cfg(unix)]
80 Self::Unix(_) => AddressFamily::UNIX,
81 #[cfg(target_os = "linux")]
82 Self::Xdp(_) => AddressFamily::XDP,
83 }
84 }
85
86 /// Writes a platform-specific encoding of this socket address to
87 /// the memory pointed to by `storage`, and returns the number of
88 /// bytes used.
89 ///
90 /// # Safety
91 ///
92 /// `storage` must point to valid memory for encoding the socket
93 /// address.
94 pub unsafe fn write(&self, storage: *mut SocketAddrStorage) -> usize {
95 backend::net::write_sockaddr::write_sockaddr(self, storage)
96 }
97
98 /// Reads a platform-specific encoding of a socket address from
99 /// the memory pointed to by `storage`, which uses `len` bytes.
100 ///
101 /// # Safety
102 ///
103 /// `storage` must point to valid memory for decoding a socket
104 /// address.
105 pub unsafe fn read(storage: *const SocketAddrStorage, len: usize) -> io::Result<Self> {
106 backend::net::read_sockaddr::read_sockaddr(storage, len)
107 }
108}
109
110#[cfg(feature = "std")]
111impl fmt::Debug for SocketAddrAny {
112 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
113 match self {
114 Self::V4(v4: &SocketAddrV4) => v4.fmt(fmt),
115 Self::V6(v6: &SocketAddrV6) => v6.fmt(fmt),
116 #[cfg(unix)]
117 Self::Unix(unix: &SocketAddrUnix) => unix.fmt(fmt),
118 #[cfg(target_os = "linux")]
119 Self::Xdp(xdp: &SocketAddrXdp) => xdp.fmt(fmt),
120 }
121 }
122}
123