@@ -13,6 +13,8 @@ use std::os::windows::prelude::*;
13
13
14
14
use net2:: TcpBuilder ;
15
15
use winapi:: * ;
16
+ use winapi:: shared:: inaddr:: { in_addr_S_un, IN_ADDR } ;
17
+ use winapi:: shared:: in6addr:: { in6_addr_u, IN6_ADDR } ;
16
18
use ws2_32:: * ;
17
19
18
20
/// 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>> {
478
480
}
479
481
}
480
482
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 ) {
482
500
match * addr {
483
501
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 )
485
517
}
486
518
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 )
488
540
}
489
541
}
490
542
}
@@ -643,7 +695,7 @@ unsafe fn connect_overlapped(socket: SOCKET,
643
695
644
696
let ( addr_buf, addr_len) = socket_addr_to_ptrs ( addr) ;
645
697
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,
647
699
buf. as_ptr ( ) as * mut _ ,
648
700
buf. len ( ) as u32 ,
649
701
& mut bytes_sent, overlapped) ;
@@ -694,7 +746,7 @@ impl UdpSocketExt for UdpSocket {
694
746
let mut sent_bytes = 0 ;
695
747
let r = WSASendTo ( self . as_raw_socket ( ) , & mut buf, 1 ,
696
748
& mut sent_bytes, 0 ,
697
- addr_buf as * const _ , addr_len,
749
+ addr_buf. as_ptr ( ) as * const _ , addr_len,
698
750
overlapped, None ) ;
699
751
cvt ( r, sent_bytes)
700
752
}
0 commit comments