|
1 | 1 | use std::fmt;
|
2 | 2 | use std::mem::{self, MaybeUninit};
|
3 |
| -use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; |
| 3 | +use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; |
4 | 4 | use std::ptr;
|
5 | 5 |
|
6 | 6 | #[cfg(any(unix, target_os = "redox"))]
|
@@ -124,33 +124,42 @@ impl SockAddr {
|
124 | 124 | }
|
125 | 125 | }
|
126 | 126 |
|
127 |
| - unsafe fn as_<T>(&self, family: sa_family_t) -> Option<T> { |
128 |
| - if self.storage.ss_family != family { |
129 |
| - return None; |
130 |
| - } |
131 |
| - |
132 |
| - Some(mem::transmute_copy(&self.storage)) |
133 |
| - } |
134 |
| - |
135 | 127 | /// Returns this address as a `SocketAddrV4` if it is in the `AF_INET`
|
136 | 128 | /// family.
|
137 | 129 | pub fn as_inet(&self) -> Option<SocketAddrV4> {
|
138 |
| - unsafe { self.as_(AF_INET as sa_family_t) } |
| 130 | + match self.as_std() { |
| 131 | + Some(SocketAddr::V4(addr)) => Some(addr), |
| 132 | + _ => None, |
| 133 | + } |
139 | 134 | }
|
140 | 135 |
|
141 | 136 | /// Returns this address as a `SocketAddrV6` if it is in the `AF_INET6`
|
142 | 137 | /// family.
|
143 | 138 | pub fn as_inet6(&self) -> Option<SocketAddrV6> {
|
144 |
| - unsafe { self.as_(AF_INET6 as sa_family_t) } |
| 139 | + match self.as_std() { |
| 140 | + Some(SocketAddr::V6(addr)) => Some(addr), |
| 141 | + _ => None, |
| 142 | + } |
145 | 143 | }
|
146 | 144 |
|
147 | 145 | /// Returns this address as a `SocketAddr` if it is in the `AF_INET`
|
148 | 146 | /// or `AF_INET6` family, otherwise returns `None`.
|
149 | 147 | pub fn as_std(&self) -> Option<SocketAddr> {
|
150 |
| - if let Some(addr) = self.as_inet() { |
151 |
| - Some(SocketAddr::V4(addr)) |
152 |
| - } else if let Some(addr) = self.as_inet6() { |
153 |
| - Some(SocketAddr::V6(addr)) |
| 148 | + if self.storage.ss_family == AF_INET as sa_family_t { |
| 149 | + let addr = unsafe { &*(&self.storage as *const _ as *const sockaddr_in) }; |
| 150 | + let ip = Ipv4Addr::from(addr.sin_addr.s_addr.to_ne_bytes()); |
| 151 | + let port = u16::from_be(addr.sin_port); |
| 152 | + Some(SocketAddr::V4(SocketAddrV4::new(ip, port))) |
| 153 | + } else if self.storage.ss_family == AF_INET6 as sa_family_t { |
| 154 | + let addr = unsafe { &*(&self.storage as *const _ as *const sockaddr_in6) }; |
| 155 | + let ip = Ipv6Addr::from(addr.sin6_addr.s6_addr); |
| 156 | + let port = u16::from_be(addr.sin6_port); |
| 157 | + Some(SocketAddr::V6(SocketAddrV6::new( |
| 158 | + ip, |
| 159 | + port, |
| 160 | + addr.sin6_flowinfo, |
| 161 | + addr.sin6_scope_id, |
| 162 | + ))) |
154 | 163 | } else {
|
155 | 164 | None
|
156 | 165 | }
|
|
0 commit comments