Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove the deprecated CmsgSpace #1156

Merged
merged 1 commit into from
Dec 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#1148](https://github.com/nix-rust/nix/pull/1148))

### Changed
- `sys::socket::recvmsg` now takes a plain `Vec` instead of a `CmsgBuffer`
implementor. If you were already using `cmsg_space!`, then you needn't worry.
([#1156](https://github.com/nix-rust/nix/pull/1156))

- `sys::socket::recvfrom` now returns
`Result<(usize, Option<SockAddr>)>` instead of `Result<(usize, SockAddr)>`.
([#1145](https://github.com/nix-rust/nix/pull/1145))
Expand Down Expand Up @@ -77,6 +81,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#1136](https://github.com/nix-rust/nix/pull/1136))

### Removed
- Remove the deprecated `CmsgSpace`.
([#1156](https://github.com/nix-rust/nix/pull/1156))

## [0.15.0] - 10 August 2019
### Added
Expand Down
121 changes: 32 additions & 89 deletions src/sys/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,21 +261,6 @@ impl Ipv6MembershipRequest {
}
}

cfg_if! {
// Darwin and DragonFly BSD always align struct cmsghdr to 32-bit only.
if #[cfg(any(target_os = "dragonfly", target_os = "ios", target_os = "macos"))] {
type align_of_cmsg_data = u32;
} else {
type align_of_cmsg_data = size_t;
}
}

/// A type that can be used to store ancillary data received by
/// [`recvmsg`](fn.recvmsg.html)
pub trait CmsgBuffer {
fn as_bytes_mut(&mut self) -> &mut [u8];
}

/// Create a buffer large enough for storing some control messages as returned
/// by [`recvmsg`](fn.recvmsg.html).
///
Expand Down Expand Up @@ -311,63 +296,11 @@ macro_rules! cmsg_space {
CMSG_SPACE(mem::size_of::<$x>() as c_uint)
} as usize;
)*
let mut v = Vec::<u8>::with_capacity(space);
// safe because any bit pattern is a valid u8
unsafe {v.set_len(space)};
v
Vec::<u8>::with_capacity(space)
}
}
}

/// A structure used to make room in a cmsghdr passed to recvmsg. The
/// size and alignment match that of a cmsghdr followed by a T, but the
/// fields are not accessible, as the actual types will change on a call
/// to recvmsg.
///
/// To make room for multiple messages, nest the type parameter with
/// tuples:
///
/// ```
/// use std::os::unix::io::RawFd;
/// use nix::sys::socket::CmsgSpace;
/// let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new();
/// ```
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct CmsgSpace<T> {
_hdr: cmsghdr,
_pad: [align_of_cmsg_data; 0],
_data: T,
}

impl<T> CmsgSpace<T> {
/// Create a CmsgSpace<T>. The structure is used only for space, so
/// the fields are uninitialized.
#[deprecated( since="0.14.0", note="Use the cmsg_space! macro instead")]
// It's deprecated anyway; no sense adding Default
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
// Safe because the fields themselves aren't accessible.
unsafe { mem::uninitialized() }
}
}

impl<T> CmsgBuffer for CmsgSpace<T> {
fn as_bytes_mut(&mut self) -> &mut [u8] {
// Safe because nothing ever attempts to access CmsgSpace's fields
unsafe {
slice::from_raw_parts_mut(self as *mut CmsgSpace<T> as *mut u8,
mem::size_of::<Self>())
}
}
}

impl CmsgBuffer for Vec<u8> {
fn as_bytes_mut(&mut self) -> &mut [u8] {
&mut self[..]
}
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RecvMsg<'a> {
pub bytes: usize,
Expand Down Expand Up @@ -893,33 +826,39 @@ pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
/// optionally receive ancillary data into the provided buffer.
/// If no ancillary data is desired, use () as the type parameter.
///
/// # Arguments
///
/// * `fd`: Socket file descriptor
/// * `iov`: Scatter-gather list of buffers to receive the message
/// * `cmsg_buffer`: Space to receive ancillary data. Should be created by
/// [`cmsg_space!`](macro.cmsg_space.html)
/// * `flags`: Optional flags passed directly to the operating system.
///
/// # References
/// [recvmsg(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
cmsg_buffer: Option<&'a mut dyn CmsgBuffer>,
mut cmsg_buffer: Option<&'a mut Vec<u8>>,
flags: MsgFlags) -> Result<RecvMsg<'a>>
{
let mut address = mem::MaybeUninit::uninit();
let (msg_control, msg_controllen) = match cmsg_buffer {
Some(cmsgspace) => {
let msg_buf = cmsgspace.as_bytes_mut();
(msg_buf.as_mut_ptr(), msg_buf.len())
},
None => (ptr::null_mut(), 0),
};
let mut mhdr = unsafe {
// Musl's msghdr has private fields, so this is the only way to
// initialize it.
let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
let p = mhdr.as_mut_ptr();
(*p).msg_name = address.as_mut_ptr() as *mut c_void;
(*p).msg_namelen = mem::size_of::<sockaddr_storage>() as socklen_t;
(*p).msg_iov = iov.as_ptr() as *mut iovec;
(*p).msg_iovlen = iov.len() as _;
(*p).msg_control = msg_control as *mut c_void;
(*p).msg_controllen = msg_controllen as _;
(*p).msg_flags = 0;
mhdr.assume_init()
let (msg_control, msg_controllen) = cmsg_buffer.as_mut()
.map(|v| (v.as_mut_ptr(), v.capacity()))
.unwrap_or((ptr::null_mut(), 0));
let mut mhdr = {
unsafe {
// Musl's msghdr has private fields, so this is the only way to
// initialize it.
let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
let p = mhdr.as_mut_ptr();
(*p).msg_name = address.as_mut_ptr() as *mut c_void;
(*p).msg_namelen = mem::size_of::<sockaddr_storage>() as socklen_t;
(*p).msg_iov = iov.as_ptr() as *mut iovec;
(*p).msg_iovlen = iov.len() as _;
(*p).msg_control = msg_control as *mut c_void;
(*p).msg_controllen = msg_controllen as _;
(*p).msg_flags = 0;
mhdr.assume_init()
}
};

let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
Expand All @@ -928,6 +867,10 @@ pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
let cmsghdr = unsafe {
if mhdr.msg_controllen > 0 {
// got control message(s)
cmsg_buffer
.as_mut()
.unwrap()
.set_len(mhdr.msg_controllen as usize);
debug_assert!(!mhdr.msg_control.is_null());
debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
CMSG_FIRSTHDR(&mhdr as *const msghdr)
Expand Down