posix_socket/address/
mod.rs1use std::os::raw::c_int;
2
3mod inet4;
4mod inet6;
5mod unix;
6
7pub use inet4::*;
8pub use inet6::*;
9pub use unix::*;
10
11pub trait GenericSocketAddress: AsSocketAddress {}
15
16pub trait SpecificSocketAddress: AsSocketAddress {
18 fn static_family() -> libc::sa_family_t;
20}
21
22pub unsafe trait AsSocketAddress: Sized {
28 fn as_sockaddr(&self) -> *const libc::sockaddr;
33
34 fn len(&self) -> libc::socklen_t;
38
39 fn family(&self) -> libc::sa_family_t {
41 unsafe {
42 (*self.as_sockaddr()).sa_family
43 }
44 }
45
46 fn as_sockaddr_mut(address: &mut std::mem::MaybeUninit<Self>) -> *mut libc::sockaddr;
51
52 fn max_len() -> libc::socklen_t;
57
58 fn finalize(address: std::mem::MaybeUninit<Self>, len: libc::socklen_t) -> std::io::Result<Self>;
63}
64
65#[derive(Clone)]
67#[repr(C)]
68pub struct SocketAddress {
69 inner: libc::sockaddr_storage,
71
72 len: libc::socklen_t,
74}
75
76impl SocketAddress {
77 pub fn from_raw(inner: libc::sockaddr_storage, len: libc::socklen_t) -> Self {
79 Self { inner, len }
80 }
81
82 pub fn from_other<Address: AsSocketAddress>(other: &Address) -> Self {
84 unsafe {
85 let mut output = std::mem::MaybeUninit::zeroed();
86 std::ptr::copy(
87 other.as_sockaddr(),
88 AsSocketAddress::as_sockaddr_mut(&mut output),
89 other.len() as usize
90 );
91 AsSocketAddress::finalize(output, other.len()).unwrap()
92 }
93 }
94
95 pub fn into_raw(self) -> (libc::sockaddr_storage, libc::socklen_t) {
97 (self.inner, self.len)
98 }
99
100 pub fn family(&self) -> c_int {
102 self.inner.ss_family as c_int
103 }
104
105 pub fn as_inet4(&self) -> Option<Inet4SocketAddress> {
109 if self.family() == libc::AF_INET {
110 let addr: &libc::sockaddr_in = unsafe { std::mem::transmute(&self.inner) };
111 Some(Inet4SocketAddress::from_raw(*addr))
112 } else {
113 None
114 }
115 }
116
117 pub fn as_inet6(&self) -> Option<Inet6SocketAddress> {
121 if self.family() == libc::AF_INET6 {
122 let addr: &libc::sockaddr_in6 = unsafe { std::mem::transmute(&self.inner) };
123 Some(Inet6SocketAddress::from_raw(*addr))
124 } else {
125 None
126 }
127 }
128
129 pub fn as_unix(&self) -> Option<UnixSocketAddress> {
133 if self.family() == libc::AF_LOCAL {
134 let addr: &libc::sockaddr_un = unsafe { std::mem::transmute(&self.inner) };
135 Some(UnixSocketAddress::from_raw(*addr, self.len))
136 } else {
137 None
138 }
139 }
140}
141
142unsafe impl AsSocketAddress for SocketAddress {
143 fn as_sockaddr(&self) -> *const libc::sockaddr {
144 &self.inner as *const _ as *const _
145 }
146
147 fn as_sockaddr_mut(address: &mut std::mem::MaybeUninit<Self>) -> *mut libc::sockaddr {
148 unsafe { &mut address.as_mut_ptr().as_mut().unwrap().inner as *mut _ as *mut _ }
149 }
150
151 fn len(&self) -> libc::socklen_t {
152 self.len
153 }
154
155 fn finalize(address: std::mem::MaybeUninit<Self>, len: libc::socklen_t) -> std::io::Result<Self> {
156 unsafe {
157 let mut address = address.assume_init();
158 if len > Self::max_len() {
159 return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "address too large"));
160 }
161 address.len = len;
162 Ok(address)
163 }
164 }
165
166 fn max_len() -> libc::socklen_t {
167 std::mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t
168 }
169}
170
171impl GenericSocketAddress for SocketAddress {}