@@ -13,6 +13,8 @@ use std::sync::atomic::{AtomicUsize, Ordering};
13
13
14
14
use winapi:: ctypes:: * ;
15
15
use winapi:: shared:: guiddef:: * ;
16
+ use winapi:: shared:: in6addr:: { in6_addr_u, IN6_ADDR } ;
17
+ use winapi:: shared:: inaddr:: { in_addr_S_un, IN_ADDR } ;
16
18
use winapi:: shared:: minwindef:: * ;
17
19
use winapi:: shared:: minwindef:: { FALSE , TRUE } ;
18
20
use winapi:: shared:: ntdef:: * ;
@@ -456,16 +458,64 @@ fn cvt(i: c_int, size: DWORD) -> io::Result<Option<usize>> {
456
458
}
457
459
}
458
460
459
- fn socket_addr_to_ptrs ( addr : & SocketAddr ) -> ( * const SOCKADDR , c_int ) {
461
+ /// A type with the same memory layout as `SOCKADDR`. Used in converting Rust level
462
+ /// SocketAddr* types into their system representation. The benefit of this specific
463
+ /// type over using `SOCKADDR_STORAGE` is that this type is exactly as large as it
464
+ /// needs to be and not a lot larger. And it can be initialized cleaner from Rust.
465
+ #[ repr( C ) ]
466
+ pub ( crate ) union SocketAddrCRepr {
467
+ v4 : SOCKADDR_IN ,
468
+ v6 : SOCKADDR_IN6_LH ,
469
+ }
470
+
471
+ impl SocketAddrCRepr {
472
+ pub ( crate ) fn as_ptr ( & self ) -> * const SOCKADDR {
473
+ self as * const _ as * const SOCKADDR
474
+ }
475
+ }
476
+
477
+ fn socket_addr_to_ptrs ( addr : & SocketAddr ) -> ( SocketAddrCRepr , c_int ) {
460
478
match * addr {
461
- SocketAddr :: V4 ( ref a) => (
462
- a as * const _ as * const _ ,
463
- mem:: size_of :: < SOCKADDR_IN > ( ) as c_int ,
464
- ) ,
465
- SocketAddr :: V6 ( ref a) => (
466
- a as * const _ as * const _ ,
467
- mem:: size_of :: < SOCKADDR_IN6_LH > ( ) as c_int ,
468
- ) ,
479
+ SocketAddr :: V4 ( ref a) => {
480
+ let sin_addr = unsafe {
481
+ let mut s_un = mem:: zeroed :: < in_addr_S_un > ( ) ;
482
+ * s_un. S_addr_mut ( ) = u32:: from_ne_bytes ( a. ip ( ) . octets ( ) ) ;
483
+ IN_ADDR { S_un : s_un }
484
+ } ;
485
+
486
+ let sockaddr_in = SOCKADDR_IN {
487
+ sin_family : AF_INET as ADDRESS_FAMILY ,
488
+ sin_port : a. port ( ) . to_be ( ) ,
489
+ sin_addr,
490
+ sin_zero : [ 0 ; 8 ] ,
491
+ } ;
492
+
493
+ let sockaddr = SocketAddrCRepr { v4 : sockaddr_in } ;
494
+ ( sockaddr, mem:: size_of :: < SOCKADDR_IN > ( ) as c_int )
495
+ }
496
+ SocketAddr :: V6 ( ref a) => {
497
+ let sin6_addr = unsafe {
498
+ let mut u = mem:: zeroed :: < in6_addr_u > ( ) ;
499
+ * u. Byte_mut ( ) = a. ip ( ) . octets ( ) ;
500
+ IN6_ADDR { u }
501
+ } ;
502
+ let u = unsafe {
503
+ let mut u = mem:: zeroed :: < SOCKADDR_IN6_LH_u > ( ) ;
504
+ * u. sin6_scope_id_mut ( ) = a. scope_id ( ) ;
505
+ u
506
+ } ;
507
+
508
+ let sockaddr_in6 = SOCKADDR_IN6_LH {
509
+ sin6_family : AF_INET6 as ADDRESS_FAMILY ,
510
+ sin6_port : a. port ( ) . to_be ( ) ,
511
+ sin6_addr,
512
+ sin6_flowinfo : a. flowinfo ( ) ,
513
+ u,
514
+ } ;
515
+
516
+ let sockaddr = SocketAddrCRepr { v6 : sockaddr_in6 } ;
517
+ ( sockaddr, mem:: size_of :: < SOCKADDR_IN6_LH > ( ) as c_int )
518
+ }
469
519
}
470
520
}
471
521
@@ -650,7 +700,7 @@ unsafe fn connect_overlapped(
650
700
let mut bytes_sent: DWORD = 0 ;
651
701
let r = connect_ex (
652
702
socket,
653
- addr_buf,
703
+ addr_buf. as_ptr ( ) ,
654
704
addr_len,
655
705
buf. as_ptr ( ) as * mut _ ,
656
706
buf. len ( ) as u32 ,
@@ -723,7 +773,7 @@ impl UdpSocketExt for UdpSocket {
723
773
1 ,
724
774
& mut sent_bytes,
725
775
0 ,
726
- addr_buf as * const _ ,
776
+ addr_buf. as_ptr ( ) as * const _ ,
727
777
addr_len,
728
778
overlapped,
729
779
None ,
0 commit comments