@@ -32,7 +32,7 @@ impl Socket {
32
32
pub fn bind ( & self , addr : & SocketAddr ) -> io:: Result < ( ) > {
33
33
let ( addr, len) = addr2raw ( addr) ;
34
34
unsafe {
35
- :: cvt ( c:: bind ( self . inner . raw ( ) , addr, len as c:: socklen_t ) ) . map ( |_| ( ) )
35
+ :: cvt ( c:: bind ( self . inner . raw ( ) , addr. as_ptr ( ) , len as c:: socklen_t ) ) . map ( |_| ( ) )
36
36
}
37
37
}
38
38
@@ -45,7 +45,7 @@ impl Socket {
45
45
pub fn connect ( & self , addr : & SocketAddr ) -> io:: Result < ( ) > {
46
46
let ( addr, len) = addr2raw ( addr) ;
47
47
unsafe {
48
- :: cvt ( c:: connect ( self . inner . raw ( ) , addr, len) ) . map ( |_| ( ) )
48
+ :: cvt ( c:: connect ( self . inner . raw ( ) , addr. as_ptr ( ) , len) ) . map ( |_| ( ) )
49
49
}
50
50
}
51
51
@@ -84,17 +84,130 @@ impl ::IntoInner for Socket {
84
84
fn into_inner ( self ) -> sys:: Socket { self . inner }
85
85
}
86
86
87
- fn addr2raw ( addr : & SocketAddr ) -> ( * const c:: sockaddr , c:: socklen_t ) {
88
- match * addr {
89
- SocketAddr :: V4 ( ref a) => {
90
- ( a as * const _ as * const _ , mem:: size_of_val ( a) as c:: socklen_t )
91
- }
92
- SocketAddr :: V6 ( ref a) => {
93
- ( a as * const _ as * const _ , mem:: size_of_val ( a) as c:: socklen_t )
94
- }
87
+ /// A type with the same memory layout as `c::sockaddr`. Used in converting Rust level
88
+ /// SocketAddr* types into their system representation. The benefit of this specific
89
+ /// type over using `c::sockaddr_storage` is that this type is exactly as large as it
90
+ /// needs to be and not a lot larger.
91
+ #[ repr( C ) ]
92
+ pub ( crate ) union SocketAddrCRepr {
93
+ v4 : c:: sockaddr_in ,
94
+ v6 : c:: sockaddr_in6 ,
95
+ }
96
+
97
+ impl SocketAddrCRepr {
98
+ pub ( crate ) fn as_ptr ( & self ) -> * const c:: sockaddr {
99
+ self as * const _ as * const c:: sockaddr
95
100
}
96
101
}
97
102
103
+ fn addr2raw ( addr : & SocketAddr ) -> ( SocketAddrCRepr , c:: socklen_t ) {
104
+ match addr {
105
+ & SocketAddr :: V4 ( ref v4) => addr2raw_v4 ( v4) ,
106
+ & SocketAddr :: V6 ( ref v6) => addr2raw_v6 ( v6) ,
107
+ }
108
+ }
109
+
110
+ #[ cfg( unix) ]
111
+ fn addr2raw_v4 ( addr : & SocketAddrV4 ) -> ( SocketAddrCRepr , c:: socklen_t ) {
112
+ let sin_addr = c:: in_addr {
113
+ s_addr : u32:: from ( * addr. ip ( ) ) . to_be ( ) ,
114
+ } ;
115
+
116
+ let sockaddr = SocketAddrCRepr {
117
+ v4 : c:: sockaddr_in {
118
+ sin_family : c:: AF_INET as c:: sa_family_t ,
119
+ sin_port : addr. port ( ) . to_be ( ) ,
120
+ sin_addr,
121
+ sin_zero : [ 0 ; 8 ] ,
122
+ #[ cfg( any(
123
+ target_os = "dragonfly" ,
124
+ target_os = "freebsd" ,
125
+ target_os = "ios" ,
126
+ target_os = "macos" ,
127
+ target_os = "netbsd" ,
128
+ target_os = "openbsd"
129
+ ) ) ]
130
+ sin_len : 0 ,
131
+ } ,
132
+ } ;
133
+ ( sockaddr, mem:: size_of :: < c:: sockaddr_in > ( ) as c:: socklen_t )
134
+ }
135
+
136
+ #[ cfg( windows) ]
137
+ fn addr2raw_v4 ( addr : & SocketAddrV4 ) -> ( SocketAddrCRepr , c:: socklen_t ) {
138
+ let sin_addr = unsafe {
139
+ let mut s_un = mem:: zeroed :: < c:: in_addr_S_un > ( ) ;
140
+ * s_un. S_addr_mut ( ) = u32:: from ( * addr. ip ( ) ) . to_be ( ) ;
141
+ c:: IN_ADDR { S_un : s_un }
142
+ } ;
143
+
144
+ let sockaddr = SocketAddrCRepr {
145
+ v4 : c:: sockaddr_in {
146
+ sin_family : c:: AF_INET as c:: sa_family_t ,
147
+ sin_port : addr. port ( ) . to_be ( ) ,
148
+ sin_addr,
149
+ sin_zero : [ 0 ; 8 ] ,
150
+ } ,
151
+ } ;
152
+ ( sockaddr, mem:: size_of :: < c:: sockaddr_in > ( ) as c:: socklen_t )
153
+ }
154
+
155
+ #[ cfg( unix) ]
156
+ fn addr2raw_v6 ( addr : & SocketAddrV6 ) -> ( SocketAddrCRepr , c:: socklen_t ) {
157
+ let sin6_addr = {
158
+ let mut sin6_addr = unsafe { mem:: zeroed :: < c:: in6_addr > ( ) } ;
159
+ sin6_addr. s6_addr = addr. ip ( ) . octets ( ) ;
160
+ sin6_addr
161
+ } ;
162
+
163
+ let sockaddr = SocketAddrCRepr {
164
+ v6 : c:: sockaddr_in6 {
165
+ sin6_family : c:: AF_INET6 as c:: sa_family_t ,
166
+ sin6_port : addr. port ( ) . to_be ( ) ,
167
+ sin6_addr,
168
+ sin6_flowinfo : addr. flowinfo ( ) ,
169
+ sin6_scope_id : addr. scope_id ( ) ,
170
+ #[ cfg( any(
171
+ target_os = "dragonfly" ,
172
+ target_os = "freebsd" ,
173
+ target_os = "ios" ,
174
+ target_os = "macos" ,
175
+ target_os = "netbsd" ,
176
+ target_os = "openbsd"
177
+ ) ) ]
178
+ sin6_len : 0 ,
179
+ #[ cfg( any( target_os = "solaris" , target_os = "illumos" ) ) ]
180
+ __sin6_src_id : 0 ,
181
+ } ,
182
+ } ;
183
+ ( sockaddr, mem:: size_of :: < c:: sockaddr_in6 > ( ) as c:: socklen_t )
184
+ }
185
+
186
+ #[ cfg( windows) ]
187
+ fn addr2raw_v6 ( addr : & SocketAddrV6 ) -> ( SocketAddrCRepr , c:: socklen_t ) {
188
+ let sin6_addr = unsafe {
189
+ let mut u = mem:: zeroed :: < c:: in6_addr_u > ( ) ;
190
+ * u. Byte_mut ( ) = addr. ip ( ) . octets ( ) ;
191
+ c:: IN6_ADDR { u }
192
+ } ;
193
+ let scope_id = unsafe {
194
+ let mut u = mem:: zeroed :: < c:: SOCKADDR_IN6_LH_u > ( ) ;
195
+ * u. sin6_scope_id_mut ( ) = addr. scope_id ( ) ;
196
+ u
197
+ } ;
198
+
199
+ let sockaddr = SocketAddrCRepr {
200
+ v6 : c:: sockaddr_in6 {
201
+ sin6_family : c:: AF_INET6 as c:: sa_family_t ,
202
+ sin6_port : addr. port ( ) . to_be ( ) ,
203
+ sin6_addr,
204
+ sin6_flowinfo : addr. flowinfo ( ) ,
205
+ u : scope_id,
206
+ } ,
207
+ } ;
208
+ ( sockaddr, mem:: size_of :: < c:: sockaddr_in6 > ( ) as c:: socklen_t )
209
+ }
210
+
98
211
fn raw2addr ( storage : & c:: sockaddr_storage , len : c:: socklen_t ) -> io:: Result < SocketAddr > {
99
212
match storage. ss_family as c_int {
100
213
c:: AF_INET => {
0 commit comments