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" )] |
13 | use crate::net::xdp::SocketAddrXdp; |
14 | #[cfg (unix)] |
15 | use crate::net::SocketAddrUnix; |
16 | use crate::net::{AddressFamily, SocketAddr, SocketAddrV4, SocketAddrV6}; |
17 | use crate::{backend, io}; |
18 | #[cfg (feature = "std" )] |
19 | use core::fmt; |
20 | |
21 | pub 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 ] |
27 | pub 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 | |
40 | impl 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 | |
50 | impl From<SocketAddrV4> for SocketAddrAny { |
51 | #[inline ] |
52 | fn from(from: SocketAddrV4) -> Self { |
53 | Self::V4(from) |
54 | } |
55 | } |
56 | |
57 | impl From<SocketAddrV6> for SocketAddrAny { |
58 | #[inline ] |
59 | fn from(from: SocketAddrV6) -> Self { |
60 | Self::V6(from) |
61 | } |
62 | } |
63 | |
64 | #[cfg (unix)] |
65 | impl From<SocketAddrUnix> for SocketAddrAny { |
66 | #[inline ] |
67 | fn from(from: SocketAddrUnix) -> Self { |
68 | Self::Unix(from) |
69 | } |
70 | } |
71 | |
72 | impl 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" )] |
111 | impl 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 | |