@@ -13,6 +13,9 @@ use std::os::windows::prelude::*;
1313
1414use net2:: TcpBuilder ;
1515use winapi:: * ;
16+ use winapi:: inaddr:: IN_ADDR ;
17+ use winapi:: ws2def:: SOCKADDR_IN ;
18+ use winapi:: ws2ipdef:: { in6_addr, sockaddr_in6} ;
1619use ws2_32:: * ;
1720
1821/// A type to represent a buffer in which a socket address will be stored.
@@ -478,13 +481,46 @@ fn cvt(i: c_int, size: DWORD) -> io::Result<Option<usize>> {
478481 }
479482}
480483
481- fn socket_addr_to_ptrs ( addr : & SocketAddr ) -> ( * const SOCKADDR , c_int ) {
484+ /// A type with the same memory layout as `SOCKADDR`. Used in converting Rust level
485+ /// SocketAddr* types into their system representation. The benefit of this specific
486+ /// type over using `SOCKADDR_STORAGE` is that this type is exactly as large as it
487+ /// needs to be and not a lot larger. And it can be initialized cleaner from Rust.
488+ #[ repr( C ) ]
489+ pub ( crate ) union SocketAddrCRepr {
490+ v4 : SOCKADDR_IN ,
491+ v6 : sockaddr_in6 ,
492+ }
493+
494+ impl SocketAddrCRepr {
495+ pub ( crate ) fn as_ptr ( & self ) -> * const SOCKADDR {
496+ self as * const _ as * const SOCKADDR
497+ }
498+ }
499+
500+ fn socket_addr_to_ptrs ( addr : & SocketAddr ) -> ( SocketAddrCRepr , c_int ) {
482501 match * addr {
483502 SocketAddr :: V4 ( ref a) => {
484- ( a as * const _ as * const _ , mem:: size_of :: < SOCKADDR_IN > ( ) as c_int )
503+ let sockaddr_in = SOCKADDR_IN {
504+ sin_family : AF_INET as ADDRESS_FAMILY ,
505+ sin_port : a. port ( ) . to_be ( ) ,
506+ sin_addr : IN_ADDR { S_un : u32:: from ( * a. ip ( ) ) . to_be ( ) } ,
507+ sin_zero : [ 0 ; 8 ] ,
508+ } ;
509+
510+ let sockaddr = SocketAddrCRepr { v4 : sockaddr_in } ;
511+ ( sockaddr, mem:: size_of :: < SOCKADDR_IN > ( ) as c_int )
485512 }
486513 SocketAddr :: V6 ( ref a) => {
487- ( a as * const _ as * const _ , mem:: size_of :: < sockaddr_in6 > ( ) as c_int )
514+ let sockaddr_in6 = sockaddr_in6 {
515+ sin6_family : AF_INET6 as i16 ,
516+ sin6_port : a. port ( ) . to_be ( ) ,
517+ sin6_addr : in6_addr { s6_addr : a. ip ( ) . octets ( ) } ,
518+ sin6_flowinfo : a. flowinfo ( ) ,
519+ sin6_scope_id : a. scope_id ( ) ,
520+ } ;
521+
522+ let sockaddr = SocketAddrCRepr { v6 : sockaddr_in6 } ;
523+ ( sockaddr, mem:: size_of :: < sockaddr_in6 > ( ) as c_int )
488524 }
489525 }
490526}
@@ -643,7 +679,7 @@ unsafe fn connect_overlapped(socket: SOCKET,
643679
644680 let ( addr_buf, addr_len) = socket_addr_to_ptrs ( addr) ;
645681 let mut bytes_sent: DWORD = 0 ;
646- let r = connect_ex ( socket, addr_buf, addr_len,
682+ let r = connect_ex ( socket, addr_buf. as_ptr ( ) , addr_len,
647683 buf. as_ptr ( ) as * mut _ ,
648684 buf. len ( ) as u32 ,
649685 & mut bytes_sent, overlapped) ;
@@ -694,7 +730,7 @@ impl UdpSocketExt for UdpSocket {
694730 let mut sent_bytes = 0 ;
695731 let r = WSASendTo ( self . as_raw_socket ( ) , & mut buf, 1 ,
696732 & mut sent_bytes, 0 ,
697- addr_buf as * const _ , addr_len,
733+ addr_buf. as_ptr ( ) as * const _ , addr_len,
698734 overlapped, None ) ;
699735 cvt ( r, sent_bytes)
700736 }
0 commit comments