@@ -32,7 +32,7 @@ impl Socket {
3232 pub fn bind ( & self , addr : & SocketAddr ) -> io:: Result < ( ) > {
3333 let ( addr, len) = addr2raw ( addr) ;
3434 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 ( |_| ( ) )
3636 }
3737 }
3838
@@ -45,7 +45,7 @@ impl Socket {
4545 pub fn connect ( & self , addr : & SocketAddr ) -> io:: Result < ( ) > {
4646 let ( addr, len) = addr2raw ( addr) ;
4747 unsafe {
48- :: cvt ( c:: connect ( self . inner . raw ( ) , addr, len) ) . map ( |_| ( ) )
48+ :: cvt ( c:: connect ( self . inner . raw ( ) , addr. as_ptr ( ) , len) ) . map ( |_| ( ) )
4949 }
5050 }
5151
@@ -84,17 +84,130 @@ impl ::IntoInner for Socket {
8484 fn into_inner ( self ) -> sys:: Socket { self . inner }
8585}
8686
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
95100 }
96101}
97102
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+
98211fn raw2addr ( storage : & c:: sockaddr_storage , len : c:: socklen_t ) -> io:: Result < SocketAddr > {
99212 match storage. ss_family as c_int {
100213 c:: AF_INET => {
0 commit comments