Skip to content

Commit 550efc2

Browse files
committed
Merge branch 'fix-sockaddr-convertion-v0.2.x' into 0.2.x
2 parents f6662ef + ca8db53 commit 550efc2

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ abstractions.
1717
winapi = "0.2"
1818
kernel32-sys = "0.2"
1919
ws2_32-sys = "0.2"
20-
net2 = { version = "0.2.5", default-features = false }
20+
net2 = { version = "0.2.36", default-features = false }
2121

2222
[dev-dependencies]
2323
rand = "0.3"

src/net.rs

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ use std::os::windows::prelude::*;
1313

1414
use net2::TcpBuilder;
1515
use winapi::*;
16+
use winapi::inaddr::IN_ADDR;
17+
use winapi::ws2def::SOCKADDR_IN;
18+
use winapi::ws2ipdef::{in6_addr, sockaddr_in6};
1619
use 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

Comments
 (0)