@@ -13,6 +13,8 @@ use std::os::windows::prelude::*;
1313
1414use net2:: TcpBuilder ;
1515use winapi:: * ;
16+ use winapi:: shared:: inaddr:: { in_addr_S_un, IN_ADDR } ;
17+ use winapi:: shared:: in6addr:: { in6_addr_u, IN6_ADDR } ;
1618use ws2_32:: * ;
1719
1820/// A type to represent a buffer in which a socket address will be stored.
@@ -478,13 +480,63 @@ fn cvt(i: c_int, size: DWORD) -> io::Result<Option<usize>> {
478480 }
479481}
480482
481- fn socket_addr_to_ptrs ( addr : & SocketAddr ) -> ( * const SOCKADDR , c_int ) {
483+ /// A type with the same memory layout as `SOCKADDR`. Used in converting Rust level
484+ /// SocketAddr* types into their system representation. The benefit of this specific
485+ /// type over using `SOCKADDR_STORAGE` is that this type is exactly as large as it
486+ /// needs to be and not a lot larger. And it can be initialized cleaner from Rust.
487+ #[ repr( C ) ]
488+ pub ( crate ) union SocketAddrCRepr {
489+ v4 : SOCKADDR_IN ,
490+ v6 : SOCKADDR_IN6_LH ,
491+ }
492+
493+ impl SocketAddrCRepr {
494+ pub ( crate ) fn as_ptr ( & self ) -> * const SOCKADDR {
495+ self as * const _ as * const SOCKADDR
496+ }
497+ }
498+
499+ fn socket_addr_to_ptrs ( addr : & SocketAddr ) -> ( SocketAddrCRepr , c_int ) {
482500 match * addr {
483501 SocketAddr :: V4 ( ref a) => {
484- ( a as * const _ as * const _ , mem:: size_of :: < SOCKADDR_IN > ( ) as c_int )
502+ let sin_addr = unsafe {
503+ let mut s_un = mem:: zeroed :: < in_addr_S_un > ( ) ;
504+ * s_un. S_addr_mut ( ) = u32:: from_ne_bytes ( a. ip ( ) . octets ( ) ) ;
505+ IN_ADDR { S_un : s_un }
506+ } ;
507+
508+ let sockaddr_in = SOCKADDR_IN {
509+ sin_family : AF_INET as ADDRESS_FAMILY ,
510+ sin_port : a. port ( ) . to_be ( ) ,
511+ sin_addr,
512+ sin_zero : [ 0 ; 8 ] ,
513+ } ;
514+
515+ let sockaddr = SocketAddrCRepr { v4 : sockaddr_in } ;
516+ ( sockaddr, mem:: size_of :: < SOCKADDR_IN > ( ) as c_int )
485517 }
486518 SocketAddr :: V6 ( ref a) => {
487- ( a as * const _ as * const _ , mem:: size_of :: < sockaddr_in6 > ( ) as c_int )
519+ let sin6_addr = unsafe {
520+ let mut u = mem:: zeroed :: < in6_addr_u > ( ) ;
521+ * u. Byte_mut ( ) = a. ip ( ) . octets ( ) ;
522+ IN6_ADDR { u }
523+ } ;
524+ let u = unsafe {
525+ let mut u = mem:: zeroed :: < SOCKADDR_IN6_LH_u > ( ) ;
526+ * u. sin6_scope_id_mut ( ) = a. scope_id ( ) ;
527+ u
528+ } ;
529+
530+ let sockaddr_in6 = SOCKADDR_IN6_LH {
531+ sin6_family : AF_INET6 as ADDRESS_FAMILY ,
532+ sin6_port : a. port ( ) . to_be ( ) ,
533+ sin6_addr,
534+ sin6_flowinfo : a. flowinfo ( ) ,
535+ u,
536+ } ;
537+
538+ let sockaddr = SocketAddrCRepr { v6 : sockaddr_in6 } ;
539+ ( sockaddr, mem:: size_of :: < SOCKADDR_IN6_LH > ( ) as c_int )
488540 }
489541 }
490542}
@@ -643,7 +695,7 @@ unsafe fn connect_overlapped(socket: SOCKET,
643695
644696 let ( addr_buf, addr_len) = socket_addr_to_ptrs ( addr) ;
645697 let mut bytes_sent: DWORD = 0 ;
646- let r = connect_ex ( socket, addr_buf, addr_len,
698+ let r = connect_ex ( socket, addr_buf. as_ptr ( ) , addr_len,
647699 buf. as_ptr ( ) as * mut _ ,
648700 buf. len ( ) as u32 ,
649701 & mut bytes_sent, overlapped) ;
@@ -694,7 +746,7 @@ impl UdpSocketExt for UdpSocket {
694746 let mut sent_bytes = 0 ;
695747 let r = WSASendTo ( self . as_raw_socket ( ) , & mut buf, 1 ,
696748 & mut sent_bytes, 0 ,
697- addr_buf as * const _ , addr_len,
749+ addr_buf. as_ptr ( ) as * const _ , addr_len,
698750 overlapped, None ) ;
699751 cvt ( r, sent_bytes)
700752 }
0 commit comments