1
1
use std:: hash:: Hash ;
2
- use std:: mem:: { self , size_of, MaybeUninit } ;
2
+ use std:: mem:: { self , size_of} ;
3
3
use std:: net:: { SocketAddr , SocketAddrV4 , SocketAddrV6 } ;
4
4
use std:: path:: Path ;
5
5
use std:: { fmt, io, ptr} ;
6
6
7
7
#[ cfg( windows) ]
8
8
use windows_sys:: Win32 :: Networking :: WinSock :: SOCKADDR_IN6_0 ;
9
9
10
- use crate :: sys:: {
11
- c_int, sa_family_t, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_storage, AF_INET , AF_INET6 ,
12
- AF_UNIX ,
13
- } ;
10
+ use crate :: sys:: { c_int, sockaddr_in, sockaddr_in6, sockaddr_storage, AF_INET , AF_INET6 , AF_UNIX } ;
14
11
use crate :: Domain ;
15
12
16
13
/// The integer type used with `getsockname` on this platform.
17
14
#[ allow( non_camel_case_types) ]
18
15
pub type socklen_t = crate :: sys:: socklen_t ;
19
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
+ unsafe { & 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
+
20
69
/// The address of a socket.
21
70
///
22
71
/// `SockAddr`s may be constructed directly to and from the standard library
@@ -44,23 +93,22 @@ impl SockAddr {
44
93
/// # fn main() -> std::io::Result<()> {
45
94
/// # #[cfg(unix)] {
46
95
/// use std::io;
47
- /// use std::mem;
48
96
/// use std::os::unix::io::AsRawFd;
49
97
///
50
- /// use socket2::{SockAddr, Socket, Domain, Type};
98
+ /// use socket2::{SockAddr, SockAddrStorage, Socket, Domain, Type};
51
99
///
52
100
/// let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?;
53
101
///
54
102
/// // Initialise a `SocketAddr` byte calling `getsockname(2)`.
55
- /// let mut addr_storage: libc::sockaddr_storage = unsafe { mem ::zeroed() } ;
56
- /// 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() ;
57
105
///
58
106
/// // The `getsockname(2)` system call will intiliase `storage` for
59
107
/// // us, setting `len` to the correct length.
60
108
/// let res = unsafe {
61
109
/// libc::getsockname(
62
110
/// socket.as_raw_fd(),
63
- /// (&mut addr_storage as *mut libc::sockaddr_storage).cast (),
111
+ /// addr_storage.view_as (),
64
112
/// &mut len,
65
113
/// )
66
114
/// };
@@ -74,8 +122,11 @@ impl SockAddr {
74
122
/// # Ok(())
75
123
/// # }
76
124
/// ```
77
- pub const unsafe fn new ( storage : sockaddr_storage , len : socklen_t ) -> SockAddr {
78
- 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
+ }
79
130
}
80
131
81
132
/// Initialise a `SockAddr` by calling the function `init`.
@@ -125,25 +176,19 @@ impl SockAddr {
125
176
/// ```
126
177
pub unsafe fn try_init < F , T > ( init : F ) -> io:: Result < ( T , SockAddr ) >
127
178
where
128
- F : FnOnce ( * mut sockaddr_storage , * mut socklen_t ) -> io:: Result < T > ,
179
+ F : FnOnce ( * mut SockAddrStorage , * mut socklen_t ) -> io:: Result < T > ,
129
180
{
130
181
const STORAGE_SIZE : socklen_t = size_of :: < sockaddr_storage > ( ) as socklen_t ;
131
182
// NOTE: `SockAddr::unix` depends on the storage being zeroed before
132
183
// calling `init`.
133
184
// NOTE: calling `recvfrom` with an empty buffer also depends on the
134
185
// storage being zeroed before calling `init` as the OS might not
135
186
// initialise it.
136
- let mut storage = MaybeUninit :: < sockaddr_storage > :: zeroed ( ) ;
187
+ let mut storage = SockAddrStorage :: zeroed ( ) ;
137
188
let mut len = STORAGE_SIZE ;
138
- init ( storage. as_mut_ptr ( ) , & mut len) . map ( |res| {
189
+ init ( & mut storage, & mut len) . map ( |res| {
139
190
debug_assert ! ( len <= STORAGE_SIZE , "overflown address storage" ) ;
140
- let addr = SockAddr {
141
- // Safety: zeroed-out `sockaddr_storage` is valid, caller must
142
- // ensure at least `len` bytes are valid.
143
- storage : storage. assume_init ( ) ,
144
- len,
145
- } ;
146
- ( res, addr)
191
+ ( res, SockAddr :: new ( storage, len) )
147
192
} )
148
193
}
149
194
@@ -183,13 +228,15 @@ impl SockAddr {
183
228
}
184
229
185
230
/// Returns a raw pointer to the address.
186
- pub const fn as_ptr ( & self ) -> * const sockaddr {
187
- 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
188
233
}
189
234
190
235
/// Retuns the address as the storage.
191
- pub const fn as_storage ( self ) -> sockaddr_storage {
192
- self . storage
236
+ pub const fn as_storage ( self ) -> SockAddrStorage {
237
+ SockAddrStorage {
238
+ storage : self . storage ,
239
+ }
193
240
}
194
241
195
242
/// Returns true if this address is in the `AF_INET` (IPv4) family, false otherwise.
0 commit comments