Skip to content

Commit bb0f3b1

Browse files
committed
Don't assume representation of SocketAddr
1 parent badc801 commit bb0f3b1

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

quinn/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ codecov = { repository = "djc/quinn" }
2727
maintenance = { status = "experimental" }
2828

2929
[dependencies]
30+
socket2 = "0.3"
3031
bytes = "1"
3132
futures = "0.3.8"
3233
libc = "0.2.69"

quinn/src/platform/unix.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,18 @@ fn send(io: &mio::net::UdpSocket, transmits: &[Transmit]) -> io::Result<usize> {
198198
let mut msgs: [libc::mmsghdr; BATCH_SIZE] = unsafe { mem::zeroed() };
199199
let mut iovecs: [libc::iovec; BATCH_SIZE] = unsafe { mem::zeroed() };
200200
let mut cmsgs = [cmsg::Aligned([0u8; CMSG_LEN]); BATCH_SIZE];
201+
let mut addrs: [MaybeUninit<socket2::SockAddr>; BATCH_SIZE] = unsafe {
202+
MaybeUninit::uninit().assume_init()
203+
};
201204
for (i, transmit) in transmits.iter().enumerate().take(BATCH_SIZE) {
205+
let dest_addr = unsafe {
206+
std::ptr::write(addrs[i].as_mut_ptr(),
207+
socket2::SockAddr::from(transmit.destination));
208+
&mut *(&mut addrs[i] as * mut _ as * mut _)
209+
};
202210
prepare_msg(
203211
transmit,
212+
dest_addr,
204213
&mut msgs[i].msg_hdr,
205214
&mut iovecs[i],
206215
&mut cmsgs[i],
@@ -233,7 +242,8 @@ fn send(io: &mio::net::UdpSocket, transmits: &[Transmit]) -> io::Result<usize> {
233242
let mut ctrl = cmsg::Aligned([0u8; CMSG_LEN]);
234243
let mut sent = 0;
235244
while sent < transmits.len() {
236-
prepare_msg(&transmits[sent], &mut hdr, &mut iov, &mut ctrl);
245+
let addr = socket2::SockAddr::from(transmits[sent].destination);
246+
prepare_msg(&transmits[sent], &addr, &mut hdr, &mut iov, &mut ctrl);
237247
let n = unsafe { libc::sendmsg(io.as_raw_fd(), &hdr, 0) };
238248
if n == -1 {
239249
let e = io::Error::last_os_error();
@@ -340,19 +350,22 @@ fn in_addr(addr: &Ipv4Addr) -> libc::in_addr {
340350

341351
fn prepare_msg(
342352
transmit: &Transmit,
353+
dest_addr: &socket2::SockAddr,
343354
hdr: &mut libc::msghdr,
344355
iov: &mut libc::iovec,
345356
ctrl: &mut cmsg::Aligned<[u8; CMSG_LEN]>,
346357
) {
347358
iov.iov_base = transmit.contents.as_ptr() as *const _ as *mut _;
348359
iov.iov_len = transmit.contents.len();
349360

350-
let (name, namelen) = match transmit.destination {
351-
SocketAddr::V4(ref addr) => (addr as *const _ as _, mem::size_of::<libc::sockaddr_in>()),
352-
SocketAddr::V6(ref addr) => (addr as *const _ as _, mem::size_of::<libc::sockaddr_in6>()),
353-
};
354-
hdr.msg_name = name;
355-
hdr.msg_namelen = namelen as _;
361+
// SAFETY: Casting the pointer to a mutable one is legal,
362+
// as sendmsg is guaranteed to not alter the mutable pointer.
363+
// The type is only mutable in the first place because it is reused
364+
// by recvmsg as well.
365+
let name = dest_addr.as_ptr() as * mut libc::c_void;
366+
let namelen = dest_addr.len();
367+
hdr.msg_name = name as *mut _;
368+
hdr.msg_namelen = namelen;
356369
hdr.msg_iov = iov;
357370
hdr.msg_iovlen = 1;
358371

0 commit comments

Comments
 (0)