Skip to content

Commit

Permalink
Merge branch 'fix-sockaddr-convertion-v0.2.x' into 0.2.x
Browse files Browse the repository at this point in the history
  • Loading branch information
faern committed Nov 27, 2020
2 parents f6662ef + ca8db53 commit 550efc2
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ abstractions.
winapi = "0.2"
kernel32-sys = "0.2"
ws2_32-sys = "0.2"
net2 = { version = "0.2.5", default-features = false }
net2 = { version = "0.2.36", default-features = false }

[dev-dependencies]
rand = "0.3"
46 changes: 41 additions & 5 deletions src/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ use std::os::windows::prelude::*;

use net2::TcpBuilder;
use winapi::*;
use winapi::inaddr::IN_ADDR;
use winapi::ws2def::SOCKADDR_IN;
use winapi::ws2ipdef::{in6_addr, sockaddr_in6};
use ws2_32::*;

/// A type to represent a buffer in which a socket address will be stored.
Expand Down Expand Up @@ -478,13 +481,46 @@ fn cvt(i: c_int, size: DWORD) -> io::Result<Option<usize>> {
}
}

fn socket_addr_to_ptrs(addr: &SocketAddr) -> (*const SOCKADDR, c_int) {
/// A type with the same memory layout as `SOCKADDR`. Used in converting Rust level
/// SocketAddr* types into their system representation. The benefit of this specific
/// type over using `SOCKADDR_STORAGE` is that this type is exactly as large as it
/// needs to be and not a lot larger. And it can be initialized cleaner from Rust.
#[repr(C)]
pub(crate) union SocketAddrCRepr {
v4: SOCKADDR_IN,
v6: sockaddr_in6,
}

impl SocketAddrCRepr {
pub(crate) fn as_ptr(&self) -> *const SOCKADDR {
self as *const _ as *const SOCKADDR
}
}

fn socket_addr_to_ptrs(addr: &SocketAddr) -> (SocketAddrCRepr, c_int) {
match *addr {
SocketAddr::V4(ref a) => {
(a as *const _ as *const _, mem::size_of::<SOCKADDR_IN>() as c_int)
let sockaddr_in = SOCKADDR_IN {
sin_family: AF_INET as ADDRESS_FAMILY,
sin_port: a.port().to_be(),
sin_addr: IN_ADDR { S_un: u32::from(*a.ip()).to_be() },
sin_zero: [0; 8],
};

let sockaddr = SocketAddrCRepr { v4: sockaddr_in };
(sockaddr, mem::size_of::<SOCKADDR_IN>() as c_int)
}
SocketAddr::V6(ref a) => {
(a as *const _ as *const _, mem::size_of::<sockaddr_in6>() as c_int)
let sockaddr_in6 = sockaddr_in6 {
sin6_family: AF_INET6 as i16,
sin6_port: a.port().to_be(),
sin6_addr: in6_addr { s6_addr: a.ip().octets() },
sin6_flowinfo: a.flowinfo(),
sin6_scope_id: a.scope_id(),
};

let sockaddr = SocketAddrCRepr { v6: sockaddr_in6 };
(sockaddr, mem::size_of::<sockaddr_in6>() as c_int)
}
}
}
Expand Down Expand Up @@ -643,7 +679,7 @@ unsafe fn connect_overlapped(socket: SOCKET,

let (addr_buf, addr_len) = socket_addr_to_ptrs(addr);
let mut bytes_sent: DWORD = 0;
let r = connect_ex(socket, addr_buf, addr_len,
let r = connect_ex(socket, addr_buf.as_ptr(), addr_len,
buf.as_ptr() as *mut _,
buf.len() as u32,
&mut bytes_sent, overlapped);
Expand Down Expand Up @@ -694,7 +730,7 @@ impl UdpSocketExt for UdpSocket {
let mut sent_bytes = 0;
let r = WSASendTo(self.as_raw_socket(), &mut buf, 1,
&mut sent_bytes, 0,
addr_buf as *const _, addr_len,
addr_buf.as_ptr() as *const _, addr_len,
overlapped, None);
cvt(r, sent_bytes)
}
Expand Down

0 comments on commit 550efc2

Please sign in to comment.