11use std:: hash:: Hash ;
2- use std:: mem:: { self , size_of, MaybeUninit } ;
2+ use std:: mem:: { self , size_of} ;
33use std:: net:: { SocketAddr , SocketAddrV4 , SocketAddrV6 } ;
44use std:: path:: Path ;
55use std:: { fmt, io, ptr} ;
66
77#[ cfg( windows) ]
88use windows_sys:: Win32 :: Networking :: WinSock :: SOCKADDR_IN6_0 ;
99
10- use crate :: sys:: {
11- c_int, sa_family_t, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_storage, socklen_t, AF_INET ,
12- AF_INET6 , AF_UNIX ,
13- } ;
10+ use crate :: sys:: { c_int, sockaddr_in, sockaddr_in6, sockaddr_storage, AF_INET , AF_INET6 , AF_UNIX } ;
1411use crate :: Domain ;
1512
13+ /// The integer type used with `getsockname` on this platform.
14+ #[ allow( non_camel_case_types) ]
15+ pub type socklen_t = crate :: sys:: socklen_t ;
16+
17+ /// The integer type for the `ss_family` field on this platform.
18+ #[ allow( non_camel_case_types) ]
19+ pub type sa_family_t = crate :: sys:: sa_family_t ;
20+
21+ /// Rust version of the [`sockaddr_storage`] type.
22+ ///
23+ /// This type is intended to be used with with direct calls to the `getsockname` syscall. See the
24+ /// documentation of [`SockAddr::new`] for examples.
25+ ///
26+ /// This crate defines its own `sockaddr_storage` type to avoid semver concerns with upgrading
27+ /// `windows-sys`.
28+ #[ repr( transparent) ]
29+ pub struct SockAddrStorage {
30+ storage : sockaddr_storage ,
31+ }
32+
33+ impl SockAddrStorage {
34+ /// Construct a new storage containing all zeros.
35+ #[ inline]
36+ pub fn zeroed ( ) -> Self {
37+ // SAFETY: All zeros is valid for this type.
38+ unsafe { mem:: zeroed ( ) }
39+ }
40+
41+ /// Returns the size of this storage.
42+ #[ inline]
43+ pub fn size_of ( & self ) -> socklen_t {
44+ size_of :: < Self > ( ) as socklen_t
45+ }
46+
47+ /// View this type as another type.
48+ ///
49+ /// # Safety
50+ ///
51+ /// The type `T` must be one of the `sockaddr_*` types defined by this platform.
52+ #[ inline]
53+ pub unsafe fn view_as < T > ( & mut self ) -> & mut T {
54+ assert ! ( size_of:: <T >( ) <= size_of:: <Self >( ) ) ;
55+ // SAFETY: This type is repr(transparent) over `sockaddr_storage` and `T` is one of the
56+ // `sockaddr_*` types defined by this platform.
57+ & mut * ( self as * mut Self as * mut T )
58+ }
59+ }
60+
61+ impl std:: fmt:: Debug for SockAddrStorage {
62+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
63+ f. debug_struct ( "sockaddr_storage" )
64+ . field ( "ss_family" , & self . storage . ss_family )
65+ . finish_non_exhaustive ( )
66+ }
67+ }
68+
1669/// The address of a socket.
1770///
1871/// `SockAddr`s may be constructed directly to and from the standard library
@@ -40,23 +93,22 @@ impl SockAddr {
4093 /// # fn main() -> std::io::Result<()> {
4194 /// # #[cfg(unix)] {
4295 /// use std::io;
43- /// use std::mem;
4496 /// use std::os::unix::io::AsRawFd;
4597 ///
46- /// use socket2::{SockAddr, Socket, Domain, Type};
98+ /// use socket2::{SockAddr, SockAddrStorage, Socket, Domain, Type};
4799 ///
48100 /// let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?;
49101 ///
50102 /// // Initialise a `SocketAddr` byte calling `getsockname(2)`.
51- /// let mut addr_storage: libc::sockaddr_storage = unsafe { mem ::zeroed() } ;
52- /// let mut len = mem::size_of_val(& addr_storage) as libc::socklen_t ;
103+ /// let mut addr_storage = SockAddrStorage ::zeroed();
104+ /// let mut len = addr_storage.size_of() ;
53105 ///
54106 /// // The `getsockname(2)` system call will intiliase `storage` for
55107 /// // us, setting `len` to the correct length.
56108 /// let res = unsafe {
57109 /// libc::getsockname(
58110 /// socket.as_raw_fd(),
59- /// (&mut addr_storage as *mut libc::sockaddr_storage).cast (),
111+ /// addr_storage.view_as (),
60112 /// &mut len,
61113 /// )
62114 /// };
@@ -70,8 +122,11 @@ impl SockAddr {
70122 /// # Ok(())
71123 /// # }
72124 /// ```
73- pub const unsafe fn new ( storage : sockaddr_storage , len : socklen_t ) -> SockAddr {
74- SockAddr { storage, len }
125+ pub const unsafe fn new ( storage : SockAddrStorage , len : socklen_t ) -> SockAddr {
126+ SockAddr {
127+ storage : storage. storage ,
128+ len : len as socklen_t ,
129+ }
75130 }
76131
77132 /// Initialise a `SockAddr` by calling the function `init`.
@@ -121,25 +176,19 @@ impl SockAddr {
121176 /// ```
122177 pub unsafe fn try_init < F , T > ( init : F ) -> io:: Result < ( T , SockAddr ) >
123178 where
124- F : FnOnce ( * mut sockaddr_storage , * mut socklen_t ) -> io:: Result < T > ,
179+ F : FnOnce ( * mut SockAddrStorage , * mut socklen_t ) -> io:: Result < T > ,
125180 {
126181 const STORAGE_SIZE : socklen_t = size_of :: < sockaddr_storage > ( ) as socklen_t ;
127182 // NOTE: `SockAddr::unix` depends on the storage being zeroed before
128183 // calling `init`.
129184 // NOTE: calling `recvfrom` with an empty buffer also depends on the
130185 // storage being zeroed before calling `init` as the OS might not
131186 // initialise it.
132- let mut storage = MaybeUninit :: < sockaddr_storage > :: zeroed ( ) ;
187+ let mut storage = SockAddrStorage :: zeroed ( ) ;
133188 let mut len = STORAGE_SIZE ;
134- init ( storage. as_mut_ptr ( ) , & mut len) . map ( |res| {
189+ init ( & mut storage, & mut len) . map ( |res| {
135190 debug_assert ! ( len <= STORAGE_SIZE , "overflown address storage" ) ;
136- let addr = SockAddr {
137- // Safety: zeroed-out `sockaddr_storage` is valid, caller must
138- // ensure at least `len` bytes are valid.
139- storage : storage. assume_init ( ) ,
140- len,
141- } ;
142- ( res, addr)
191+ ( res, SockAddr :: new ( storage, len) )
143192 } )
144193 }
145194
@@ -179,13 +228,15 @@ impl SockAddr {
179228 }
180229
181230 /// Returns a raw pointer to the address.
182- pub const fn as_ptr ( & self ) -> * const sockaddr {
183- ptr :: addr_of! ( self . storage) . cast ( )
231+ pub const fn as_ptr ( & self ) -> * const SockAddrStorage {
232+ & self . storage as * const sockaddr_storage as * const SockAddrStorage
184233 }
185234
186235 /// Retuns the address as the storage.
187- pub const fn as_storage ( self ) -> sockaddr_storage {
188- self . storage
236+ pub const fn as_storage ( self ) -> SockAddrStorage {
237+ SockAddrStorage {
238+ storage : self . storage ,
239+ }
189240 }
190241
191242 /// Returns true if this address is in the `AF_INET` (IPv4) family, false otherwise.
0 commit comments