Skip to content

Commit a7ac04f

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

File tree

2 files changed

+65
-123
lines changed

2 files changed

+65
-123
lines changed

src/sys/socket/ffi.rs

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

src/sys/socket/mod.rs

Lines changed: 65 additions & 42 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 = "ios", target_os = "macos", target_os = "dragonfly"))]
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,17 @@ 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) => {
522-
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: [],
539+
let cmsg = {
540+
let mut cmsg: cmsghdr = mem::uninitialized();
541+
cmsg.cmsg_len = self.len() as _;
542+
cmsg.cmsg_level = libc::SOL_SOCKET;
543+
cmsg.cmsg_type = libc::SCM_RIGHTS;
544+
cmsg
527545
};
528546
copy_bytes(&cmsg, buf);
529547

@@ -538,11 +556,12 @@ impl<'a> ControlMessage<'a> {
538556
copy_bytes(fds, buf);
539557
},
540558
ControlMessage::ScmTimestamp(t) => {
541-
let cmsg = cmsghdr {
542-
cmsg_len: self.len() as type_of_cmsg_len,
543-
cmsg_level: libc::SOL_SOCKET,
544-
cmsg_type: libc::SCM_TIMESTAMP,
545-
cmsg_data: [],
559+
let cmsg = {
560+
let mut cmsg: cmsghdr = mem::uninitialized();
561+
cmsg.cmsg_len = self.len() as _;
562+
cmsg.cmsg_level = libc::SOL_SOCKET;
563+
cmsg.cmsg_type = libc::SCM_TIMESTAMP;
564+
cmsg
546565
};
547566
copy_bytes(&cmsg, buf);
548567

@@ -602,16 +621,18 @@ pub fn sendmsg<'a>(fd: RawFd, iov: &[IoVec<&'a [u8]>], cmsgs: &[ControlMessage<'
602621
ptr::null()
603622
};
604623

605-
let mhdr = msghdr {
606-
msg_name: name as *const c_void,
607-
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,
612-
msg_flags: 0,
624+
let mhdr = unsafe {
625+
let mut mhdr: msghdr = mem::uninitialized();
626+
mhdr.msg_name = name as *mut _;
627+
mhdr.msg_namelen = namelen;
628+
mhdr.msg_iov = iov.as_ptr() as *mut _;
629+
mhdr.msg_iovlen = iov.len() as _;
630+
mhdr.msg_control = cmsg_ptr as *mut _;
631+
mhdr.msg_controllen = capacity as _;
632+
mhdr.msg_flags = 0;
633+
mhdr
613634
};
614-
let ret = unsafe { ffi::sendmsg(fd, &mhdr, flags.bits()) };
635+
let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
615636

616637
Errno::result(ret).map(|r| r as usize)
617638
}
@@ -625,16 +646,18 @@ pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<&
625646
Some(cmsg_buffer) => (cmsg_buffer as *mut _, mem::size_of_val(cmsg_buffer)),
626647
None => (0 as *mut _, 0),
627648
};
628-
let mut mhdr = msghdr {
629-
msg_name: &mut address as *const _ as *const c_void,
630-
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,
635-
msg_flags: 0,
649+
let mut mhdr = unsafe {
650+
let mut mhdr: msghdr = mem::uninitialized();
651+
mhdr.msg_name = &mut address as *mut _ as *mut _;
652+
mhdr.msg_namelen = mem::size_of::<sockaddr_storage>() as socklen_t;
653+
mhdr.msg_iov = iov.as_ptr() as *mut _;
654+
mhdr.msg_iovlen = iov.len() as _;
655+
mhdr.msg_control = msg_control as *mut _;
656+
mhdr.msg_controllen = msg_controllen as _;
657+
mhdr.msg_flags = 0;
658+
mhdr
636659
};
637-
let ret = unsafe { ffi::recvmsg(fd, &mut mhdr, flags.bits()) };
660+
let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
638661

639662
Ok(unsafe { RecvMsg {
640663
bytes: try!(Errno::result(ret)) as usize,
@@ -851,7 +874,7 @@ pub fn connect(fd: RawFd, addr: &SockAddr) -> Result<()> {
851874
/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
852875
pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
853876
unsafe {
854-
let ret = ffi::recv(
877+
let ret = libc::recv(
855878
sockfd,
856879
buf.as_ptr() as *mut c_void,
857880
buf.len() as size_t,
@@ -870,7 +893,7 @@ pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, SockAddr)> {
870893
let addr: sockaddr_storage = mem::zeroed();
871894
let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
872895

873-
let ret = try!(Errno::result(ffi::recvfrom(
896+
let ret = try!(Errno::result(libc::recvfrom(
874897
sockfd,
875898
buf.as_ptr() as *mut c_void,
876899
buf.len() as size_t,

0 commit comments

Comments
 (0)