Skip to content

Commit 9994365

Browse files
committed
Migrate sys/socket to libc FFI types.
1 parent b68db41 commit 9994365

File tree

2 files changed

+51
-113
lines changed

2 files changed

+51
-113
lines changed

src/sys/socket/ffi.rs

Lines changed: 0 additions & 81 deletions
This file was deleted.

src/sys/socket/mod.rs

Lines changed: 51 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use sys::time::TimeVal;
1111
use sys::uio::IoVec;
1212

1313
mod addr;
14-
mod ffi;
1514
pub mod sockopt;
1615

1716
/*
@@ -33,6 +32,8 @@ pub use self::addr::{
3332
pub use ::sys::socket::addr::netlink::NetlinkAddr;
3433

3534
pub use libc::{
35+
cmsghdr,
36+
msghdr,
3637
sa_family_t,
3738
sockaddr,
3839
sockaddr_in,
@@ -295,19 +296,30 @@ unsafe fn copy_bytes<'a, 'b, T: ?Sized>(src: &T, dst: &'a mut &'b mut [u8]) {
295296
mem::swap(dst, &mut remainder);
296297
}
297298

299+
// Darwin and DragonFly BSD always aligns struct cmsghdr as if it were a 32-bit OS
300+
#[cfg(any(target_os = "dragonfly", target_os = "ios", target_os = "macos"))]
301+
type align_of_cmsg_data = u32;
298302

299-
use self::ffi::{cmsghdr, msghdr, type_of_cmsg_data, type_of_msg_iovlen, type_of_cmsg_len};
303+
#[cfg(not(target_os = "macos"))]
304+
type align_of_cmsg_data = size_t;
300305

301306
/// A structure used to make room in a cmsghdr passed to recvmsg. The
302307
/// size and alignment match that of a cmsghdr followed by a T, but the
303308
/// fields are not accessible, as the actual types will change on a call
304309
/// to recvmsg.
305310
///
306311
/// To make room for multiple messages, nest the type parameter with
307-
/// tuples, e.g.
308-
/// `let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new();`
312+
/// tuples:
313+
///
314+
/// ```
315+
/// use std::os::unix::io::RawFd;
316+
/// use nix::sys::socket::CmsgSpace;
317+
/// let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new();
318+
/// ```
319+
#[repr(C)]
309320
pub struct CmsgSpace<T> {
310321
_hdr: cmsghdr,
322+
_pad: [align_of_cmsg_data; 0],
311323
_data: T,
312324
}
313325

@@ -377,24 +389,25 @@ impl<'a> Iterator for CmsgIterator<'a> {
377389
if aligned_cmsg_len > self.buf.len() {
378390
return None;
379391
}
392+
let cmsg_data = &self.buf[cmsg_align(sizeof_cmsghdr)..cmsg_len];
380393
self.buf = &self.buf[aligned_cmsg_len..];
381394
self.next += 1;
382395

383396
match (cmsg.cmsg_level, cmsg.cmsg_type) {
384397
(libc::SOL_SOCKET, libc::SCM_RIGHTS) => unsafe {
385398
Some(ControlMessage::ScmRights(
386-
slice::from_raw_parts(
387-
&cmsg.cmsg_data as *const _ as *const _, 1)))
399+
slice::from_raw_parts(cmsg_data.as_ptr() as *const _,
400+
cmsg_data.len() / mem::size_of::<RawFd>())))
388401
},
389402
(libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => unsafe {
390403
Some(ControlMessage::ScmTimestamp(
391-
&*(&cmsg.cmsg_data as *const _ as *const _)))
404+
&*(cmsg_data.as_ptr() as *const _)))
392405
},
393406
(_, _) => unsafe {
394407
Some(ControlMessage::Unknown(UnknownCmsg(
395408
&cmsg,
396409
slice::from_raw_parts(
397-
&cmsg.cmsg_data as *const _ as *const _,
410+
cmsg_data.as_ptr() as *const _,
398411
len))))
399412
}
400413
}
@@ -487,8 +500,13 @@ pub enum ControlMessage<'a> {
487500
#[doc(hidden)]
488501
pub struct UnknownCmsg<'a>(&'a cmsghdr, &'a [u8]);
489502

503+
// Round `len` up to meet the platform's required alignment for
504+
// `cmsghdr`s and trailing `cmsghdr` data. This should match the
505+
// behaviour of CMSG_ALIGN from the Linux headers and do the correct
506+
// thing on other platforms that don't usually provide CMSG_ALIGN.
507+
#[inline]
490508
fn cmsg_align(len: usize) -> usize {
491-
let align_bytes = mem::size_of::<type_of_cmsg_data>() - 1;
509+
let align_bytes = mem::size_of::<align_of_cmsg_data>() - 1;
492510
(len + align_bytes) & !align_bytes
493511
}
494512

@@ -513,17 +531,16 @@ impl<'a> ControlMessage<'a> {
513531
}
514532
}
515533

516-
// Unsafe: start and end of buffer must be size_t-aligned (that is,
517-
// cmsg_align'd). Updates the provided slice; panics if the buffer
518-
// is too small.
534+
// Unsafe: start and end of buffer must be cmsg_align'd. Updates
535+
// the provided slice; panics if the buffer is too small.
519536
unsafe fn encode_into<'b>(&self, buf: &mut &'b mut [u8]) {
520537
match *self {
521538
ControlMessage::ScmRights(fds) => {
522539
let cmsg = cmsghdr {
523-
cmsg_len: self.len() as type_of_cmsg_len,
524-
cmsg_level: libc::SOL_SOCKET,
525-
cmsg_type: libc::SCM_RIGHTS,
526-
cmsg_data: [],
540+
cmsg_len: self.len() as _,
541+
cmsg_level: libc::SOL_SOCKET,
542+
cmsg_type: libc::SCM_RIGHTS,
543+
..mem::uninitialized()
527544
};
528545
copy_bytes(&cmsg, buf);
529546

@@ -539,10 +556,10 @@ impl<'a> ControlMessage<'a> {
539556
},
540557
ControlMessage::ScmTimestamp(t) => {
541558
let cmsg = cmsghdr {
542-
cmsg_len: self.len() as type_of_cmsg_len,
559+
cmsg_len: self.len() as _,
543560
cmsg_level: libc::SOL_SOCKET,
544561
cmsg_type: libc::SCM_TIMESTAMP,
545-
cmsg_data: [],
562+
..mem::uninitialized()
546563
};
547564
copy_bytes(&cmsg, buf);
548565

@@ -603,15 +620,16 @@ pub fn sendmsg<'a>(fd: RawFd, iov: &[IoVec<&'a [u8]>], cmsgs: &[ControlMessage<'
603620
};
604621

605622
let mhdr = msghdr {
606-
msg_name: name as *const c_void,
623+
msg_name: name as *mut _,
607624
msg_namelen: namelen,
608-
msg_iov: iov.as_ptr(),
609-
msg_iovlen: iov.len() as type_of_msg_iovlen,
610-
msg_control: cmsg_ptr,
611-
msg_controllen: capacity as type_of_cmsg_len,
625+
msg_iov: iov.as_ptr() as *mut _,
626+
msg_iovlen: iov.len() as _,
627+
msg_control: cmsg_ptr as *mut _,
628+
msg_controllen: capacity as _,
612629
msg_flags: 0,
630+
..unsafe { mem::uninitialized() }
613631
};
614-
let ret = unsafe { ffi::sendmsg(fd, &mhdr, flags.bits()) };
632+
let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
615633

616634
Errno::result(ret).map(|r| r as usize)
617635
}
@@ -626,15 +644,16 @@ pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<&
626644
None => (0 as *mut _, 0),
627645
};
628646
let mut mhdr = msghdr {
629-
msg_name: &mut address as *const _ as *const c_void,
647+
msg_name: &mut address as *mut _ as *mut _,
630648
msg_namelen: mem::size_of::<sockaddr_storage>() as socklen_t,
631-
msg_iov: iov.as_ptr() as *const IoVec<&[u8]>, // safe cast to add const-ness
632-
msg_iovlen: iov.len() as type_of_msg_iovlen,
633-
msg_control: msg_control as *const c_void,
634-
msg_controllen: msg_controllen as type_of_cmsg_len,
649+
msg_iov: iov.as_ptr() as *mut _,
650+
msg_iovlen: iov.len() as _,
651+
msg_control: msg_control as *mut _,
652+
msg_controllen: msg_controllen as _,
635653
msg_flags: 0,
654+
..unsafe { mem::uninitialized() }
636655
};
637-
let ret = unsafe { ffi::recvmsg(fd, &mut mhdr, flags.bits()) };
656+
let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
638657

639658
Ok(unsafe { RecvMsg {
640659
bytes: try!(Errno::result(ret)) as usize,
@@ -851,7 +870,7 @@ pub fn connect(fd: RawFd, addr: &SockAddr) -> Result<()> {
851870
/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
852871
pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
853872
unsafe {
854-
let ret = ffi::recv(
873+
let ret = libc::recv(
855874
sockfd,
856875
buf.as_ptr() as *mut c_void,
857876
buf.len() as size_t,
@@ -870,7 +889,7 @@ pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, SockAddr)> {
870889
let addr: sockaddr_storage = mem::zeroed();
871890
let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
872891

873-
let ret = try!(Errno::result(ffi::recvfrom(
892+
let ret = try!(Errno::result(libc::recvfrom(
874893
sockfd,
875894
buf.as_ptr() as *mut c_void,
876895
buf.len() as size_t,

0 commit comments

Comments
 (0)