Skip to content

Commit

Permalink
Add SocketAddress trait to reduce code duplicated across address types
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinmehall committed Jan 29, 2024
1 parent d268591 commit 8533f7c
Show file tree
Hide file tree
Showing 15 changed files with 433 additions and 957 deletions.
40 changes: 40 additions & 0 deletions src/backend/libc/net/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,25 @@ use {
core::slice,
};

use super::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6};
use crate::net::{SocketAddrV4, SocketAddrV6, SocketAddress};

unsafe impl SocketAddress for SocketAddrV4 {
type CSockAddr = c::sockaddr_in;

fn encode(&self) -> Self::CSockAddr {
encode_sockaddr_v4(self)
}
}

unsafe impl SocketAddress for SocketAddrV6 {
type CSockAddr = c::sockaddr_in6;

fn encode(&self) -> Self::CSockAddr {
encode_sockaddr_v6(self)
}
}

/// `struct sockaddr_un`
#[cfg(unix)]
#[derive(Clone)]
Expand Down Expand Up @@ -202,6 +221,27 @@ impl fmt::Debug for SocketAddrUnix {
}
}

#[cfg(unix)]
unsafe impl SocketAddress for SocketAddrUnix {
type CSockAddr = c::sockaddr_un;

fn encode(&self) -> Self::CSockAddr {
self.unix
}

unsafe fn write_sockaddr(&self, storage: *mut SocketAddrStorage) -> usize {
core::ptr::write(storage.cast(), self.unix);
self.len()
}

fn with_sockaddr<R>(&self, f: impl FnOnce(*const c::sockaddr, c::socklen_t) -> R) -> R {
f(
(&self.unix as *const c::sockaddr_un).cast(),
self.addr_len(),
)
}
}

/// `struct sockaddr_storage` as a raw struct.
pub type SocketAddrStorage = c::sockaddr_storage;

Expand Down
99 changes: 15 additions & 84 deletions src/backend/libc/net/msghdr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,9 @@
use crate::backend::c;
use crate::backend::conv::{msg_control_len, msg_iov_len};
#[cfg(target_os = "linux")]
use crate::backend::net::write_sockaddr::encode_sockaddr_xdp;
use crate::backend::net::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6};

use crate::io::{self, IoSlice, IoSliceMut};
#[cfg(target_os = "linux")]
use crate::net::xdp::SocketAddrXdp;
use crate::net::{RecvAncillaryBuffer, SendAncillaryBuffer, SocketAddrV4, SocketAddrV6};
use crate::utils::as_ptr;
use crate::net::{RecvAncillaryBuffer, SendAncillaryBuffer, SocketAddress};

use core::mem::{size_of, zeroed, MaybeUninit};

Expand Down Expand Up @@ -66,87 +60,24 @@ pub(crate) fn with_noaddr_msghdr<R>(
})
}

/// Create a message header intended to send with an IPv4 address.
pub(crate) fn with_v4_msghdr<R>(
addr: &SocketAddrV4,
/// Create a message header intended to send with the specified address.
pub(crate) fn with_msghdr<R, A: SocketAddress>(
addr: &A,
iov: &[IoSlice<'_>],
control: &mut SendAncillaryBuffer<'_, '_, '_>,
f: impl FnOnce(c::msghdr) -> R,
) -> R {
let encoded = encode_sockaddr_v4(addr);

f({
let mut h = zero_msghdr();
h.msg_name = as_ptr(&encoded) as _;
h.msg_namelen = size_of::<SocketAddrV4>() as _;
h.msg_iov = iov.as_ptr() as _;
h.msg_iovlen = msg_iov_len(iov.len());
h.msg_control = control.as_control_ptr().cast();
h.msg_controllen = msg_control_len(control.control_len());
h
})
}

/// Create a message header intended to send with an IPv6 address.
pub(crate) fn with_v6_msghdr<R>(
addr: &SocketAddrV6,
iov: &[IoSlice<'_>],
control: &mut SendAncillaryBuffer<'_, '_, '_>,
f: impl FnOnce(c::msghdr) -> R,
) -> R {
let encoded = encode_sockaddr_v6(addr);

f({
let mut h = zero_msghdr();
h.msg_name = as_ptr(&encoded) as _;
h.msg_namelen = size_of::<SocketAddrV6>() as _;
h.msg_iov = iov.as_ptr() as _;
h.msg_iovlen = msg_iov_len(iov.len());
h.msg_control = control.as_control_ptr().cast();
h.msg_controllen = msg_control_len(control.control_len());
h
})
}

/// Create a message header intended to send with a Unix address.
#[cfg(all(unix, not(target_os = "redox")))]
pub(crate) fn with_unix_msghdr<R>(
addr: &crate::net::SocketAddrUnix,
iov: &[IoSlice<'_>],
control: &mut SendAncillaryBuffer<'_, '_, '_>,
f: impl FnOnce(c::msghdr) -> R,
) -> R {
f({
let mut h = zero_msghdr();
h.msg_name = as_ptr(&addr.unix) as _;
h.msg_namelen = addr.addr_len();
h.msg_iov = iov.as_ptr() as _;
h.msg_iovlen = msg_iov_len(iov.len());
h.msg_control = control.as_control_ptr().cast();
h.msg_controllen = msg_control_len(control.control_len());
h
})
}

/// Create a message header intended to send with an IPv6 address.
#[cfg(target_os = "linux")]
pub(crate) fn with_xdp_msghdr<R>(
addr: &SocketAddrXdp,
iov: &[IoSlice<'_>],
control: &mut SendAncillaryBuffer<'_, '_, '_>,
f: impl FnOnce(c::msghdr) -> R,
) -> R {
let encoded = encode_sockaddr_xdp(addr);

f({
let mut h = zero_msghdr();
h.msg_name = as_ptr(&encoded) as _;
h.msg_namelen = size_of::<SocketAddrXdp>() as _;
h.msg_iov = iov.as_ptr() as _;
h.msg_iovlen = msg_iov_len(iov.len());
h.msg_control = control.as_control_ptr().cast();
h.msg_controllen = msg_control_len(control.control_len());
h
addr.with_sockaddr(|addr_ptr, addr_len| {
f({
let mut h = zero_msghdr();
h.msg_name = addr_ptr.cast_mut().cast();
h.msg_namelen = addr_len;
h.msg_iov = iov.as_ptr() as _;
h.msg_iovlen = msg_iov_len(iov.len());
h.msg_control = control.as_control_ptr().cast();
h.msg_controllen = msg_control_len(control.control_len());
h
})
})
}

Expand Down
Loading

0 comments on commit 8533f7c

Please sign in to comment.