2 use std
::mem
::{self, MaybeUninit}
;
3 use std
::net
::{SocketAddr, SocketAddrV4, SocketAddrV6}
;
6 #[cfg(any(unix, target_os = "redox"))]
8 sa_family_t
, sockaddr
, sockaddr_in
, sockaddr_in6
, sockaddr_storage
, socklen_t
, AF_INET
,
12 use winapi
::shared
::ws2def
::{
13 ADDRESS_FAMILY
as sa_family_t
, AF_INET
, AF_INET6
, SOCKADDR
as sockaddr
,
14 SOCKADDR_IN
as sockaddr_in
, SOCKADDR_STORAGE
as sockaddr_storage
,
17 use winapi
::shared
::ws2ipdef
::SOCKADDR_IN6_LH
as sockaddr_in6
;
19 use winapi
::um
::ws2tcpip
::socklen_t
;
21 /// The address of a socket.
23 /// `SockAddr`s may be constructed directly to and from the standard library
24 /// `SocketAddr`, `SocketAddrV4`, and `SocketAddrV6` types.
26 storage
: sockaddr_storage
,
30 impl fmt
::Debug
for SockAddr
{
31 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
32 let mut builder
= fmt
.debug_struct("SockAddr");
33 builder
.field("family", &self.family());
34 if let Some(addr
) = self.as_inet() {
35 builder
.field("inet", &addr
);
36 } else if let Some(addr
) = self.as_inet6() {
37 builder
.field("inet6", &addr
);
44 /// Constructs a `SockAddr` from its raw components.
45 pub unsafe fn from_raw_parts(addr
: *const sockaddr
, len
: socklen_t
) -> SockAddr
{
46 let mut storage
= MaybeUninit
::<sockaddr_storage
>::uninit();
47 ptr
::copy_nonoverlapping(
48 addr
as *const _
as *const u8,
49 &mut storage
as *mut _
as *mut u8,
54 // This is safe as we written the address to `storage` above.
55 storage
: storage
.assume_init(),
60 /// Constructs a `SockAddr` with the family `AF_UNIX` and the provided path.
62 /// This function is only available on Unix when the `unix` feature is
67 /// Returns an error if the path is longer than `SUN_LEN`.
68 #[cfg(all(unix, feature = "unix"))]
69 pub fn unix
<P
>(path
: P
) -> ::std
::io
::Result
<SockAddr
>
71 P
: AsRef
<::std
::path
::Path
>,
73 use libc
::{c_char, sockaddr_un, AF_UNIX}
;
74 use std
::cmp
::Ordering
;
76 use std
::os
::unix
::ffi
::OsStrExt
;
79 let mut addr
= mem
::zeroed
::<sockaddr_un
>();
80 addr
.sun_family
= AF_UNIX
as sa_family_t
;
82 let bytes
= path
.as_ref().as_os_str().as_bytes();
84 match (bytes
.get(0), bytes
.len().cmp(&addr
.sun_path
.len())) {
85 // Abstract paths don't need a null terminator
86 (Some(&0), Ordering
::Greater
) => {
87 return Err(io
::Error
::new(
88 io
::ErrorKind
::InvalidInput
,
89 "path must be no longer than SUN_LEN",
93 (_
, Ordering
::Greater
) | (_
, Ordering
::Equal
) => {
94 return Err(io
::Error
::new(
95 io
::ErrorKind
::InvalidInput
,
96 "path must be shorter than SUN_LEN",
102 for (dst
, src
) in addr
.sun_path
.iter_mut().zip(bytes
) {
103 *dst
= *src
as c_char
;
105 // null byte for pathname is already there since we zeroed up front
107 let base
= &addr
as *const _
as usize;
108 let path
= &addr
.sun_path
as *const _
as usize;
109 let sun_path_offset
= path
- base
;
111 let mut len
= sun_path_offset
+ bytes
.len();
113 Some(&0) | None
=> {}
116 Ok(SockAddr
::from_raw_parts(
117 &addr
as *const _
as *const _
,
123 unsafe fn as_
<T
>(&self, family
: sa_family_t
) -> Option
<T
> {
124 if self.storage
.ss_family
!= family
{
128 Some(mem
::transmute_copy(&self.storage
))
131 /// Returns this address as a `SocketAddrV4` if it is in the `AF_INET`
133 pub fn as_inet(&self) -> Option
<SocketAddrV4
> {
134 unsafe { self.as_(AF_INET as sa_family_t) }
137 /// Returns this address as a `SocketAddrV6` if it is in the `AF_INET6`
139 pub fn as_inet6(&self) -> Option
<SocketAddrV6
> {
140 unsafe { self.as_(AF_INET6 as sa_family_t) }
143 /// Returns this address as a `SocketAddr` if it is in the `AF_INET`
144 /// or `AF_INET6` family, otherwise returns `None`.
145 pub fn as_std(&self) -> Option
<SocketAddr
> {
146 if let Some(addr
) = self.as_inet() {
147 Some(SocketAddr
::V4(addr
))
148 } else if let Some(addr
) = self.as_inet6() {
149 Some(SocketAddr
::V6(addr
))
155 /// Returns this address's family.
156 pub fn family(&self) -> sa_family_t
{
157 self.storage
.ss_family
160 /// Returns the size of this address in bytes.
161 pub fn len(&self) -> socklen_t
{
165 /// Returns a raw pointer to the address.
166 pub fn as_ptr(&self) -> *const sockaddr
{
167 &self.storage
as *const _
as *const _
171 // SocketAddrV4 and SocketAddrV6 are just wrappers around sockaddr_in and sockaddr_in6
173 // check to make sure that the sizes at least match up
174 fn _size_checks(v4
: SocketAddrV4
, v6
: SocketAddrV6
) {
176 mem
::transmute
::<SocketAddrV4
, sockaddr_in
>(v4
);
177 mem
::transmute
::<SocketAddrV6
, sockaddr_in6
>(v6
);
181 impl From
<SocketAddrV4
> for SockAddr
{
182 fn from(addr
: SocketAddrV4
) -> SockAddr
{
184 SockAddr
::from_raw_parts(
185 &addr
as *const _
as *const _
,
186 mem
::size_of
::<SocketAddrV4
>() as socklen_t
,
192 impl From
<SocketAddrV6
> for SockAddr
{
193 fn from(addr
: SocketAddrV6
) -> SockAddr
{
195 SockAddr
::from_raw_parts(
196 &addr
as *const _
as *const _
,
197 mem
::size_of
::<SocketAddrV6
>() as socklen_t
,
203 impl From
<SocketAddr
> for SockAddr
{
204 fn from(addr
: SocketAddr
) -> SockAddr
{
206 SocketAddr
::V4(addr
) => addr
.into(),
207 SocketAddr
::V6(addr
) => addr
.into(),
218 let raw
= "127.0.0.1:80".parse
::<SocketAddrV4
>().unwrap();
219 let addr
= SockAddr
::from(raw
);
220 assert
!(addr
.as_inet6().is_none());
221 let addr
= addr
.as_inet().unwrap();
222 assert_eq
!(raw
, addr
);
227 let raw
= "[2001:db8::ff00:42:8329]:80"
228 .parse
::<SocketAddrV6
>()
230 let addr
= SockAddr
::from(raw
);
231 assert
!(addr
.as_inet().is_none());
232 let addr
= addr
.as_inet6().unwrap();
233 assert_eq
!(raw
, addr
);