@@ -13,6 +13,9 @@ use std::os::windows::prelude::*;
13
13
14
14
use net2:: TcpBuilder ;
15
15
use winapi:: * ;
16
+ use winapi:: inaddr:: IN_ADDR ;
17
+ use winapi:: ws2def:: SOCKADDR_IN ;
18
+ use winapi:: ws2ipdef:: { in6_addr, sockaddr_in6} ;
16
19
use ws2_32:: * ;
17
20
18
21
/// 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>> {
478
481
}
479
482
}
480
483
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 ) {
482
501
match * addr {
483
502
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 )
485
512
}
486
513
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 )
488
524
}
489
525
}
490
526
}
@@ -643,7 +679,7 @@ unsafe fn connect_overlapped(socket: SOCKET,
643
679
644
680
let ( addr_buf, addr_len) = socket_addr_to_ptrs ( addr) ;
645
681
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,
647
683
buf. as_ptr ( ) as * mut _ ,
648
684
buf. len ( ) as u32 ,
649
685
& mut bytes_sent, overlapped) ;
@@ -694,7 +730,7 @@ impl UdpSocketExt for UdpSocket {
694
730
let mut sent_bytes = 0 ;
695
731
let r = WSASendTo ( self . as_raw_socket ( ) , & mut buf, 1 ,
696
732
& mut sent_bytes, 0 ,
697
- addr_buf as * const _ , addr_len,
733
+ addr_buf. as_ptr ( ) as * const _ , addr_len,
698
734
overlapped, None ) ;
699
735
cvt ( r, sent_bytes)
700
736
}
0 commit comments