Skip to content

Commit

Permalink
Migrate sys/socket to libc FFI types.
Browse files Browse the repository at this point in the history
  • Loading branch information
kinetiknz committed Sep 27, 2017
1 parent 9f4db8a commit b35564f
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 110 deletions.
81 changes: 0 additions & 81 deletions src/sys/socket/ffi.rs

This file was deleted.

63 changes: 34 additions & 29 deletions src/sys/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use sys::time::TimeVal;
use sys::uio::IoVec;

mod addr;
mod ffi;
mod multicast;
pub mod sockopt;

Expand All @@ -33,13 +32,15 @@ pub use self::addr::{
pub use ::sys::socket::addr::netlink::NetlinkAddr;

pub use libc::{
cmsghdr,
in_addr,
in6_addr,
msghdr,
sa_family_t,
sockaddr,
sockaddr_in,
sockaddr_in6,
sockaddr_un,
sa_family_t,
};

pub use self::multicast::{
Expand Down Expand Up @@ -187,8 +188,12 @@ unsafe fn copy_bytes<'a, 'b, T: ?Sized>(src: &T, dst: &'a mut &'b mut [u8]) {
mem::swap(dst, &mut remainder);
}

// OSX always aligns struct cmsghdr as if it were a 32-bit OS
#[cfg(target_os = "macos")]
type align_of_cmsg_data = libc::c_uint;

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

/// 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
Expand All @@ -198,8 +203,10 @@ use self::ffi::{cmsghdr, msghdr, type_of_cmsg_data, type_of_msg_iovlen, type_of_
/// To make room for multiple messages, nest the type parameter with
/// tuples, e.g.
/// `let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new();`
#[repr(C)]
pub struct CmsgSpace<T> {
_hdr: cmsghdr,
_pad: [align_of_cmsg_data; 0],
_data: T,
}

Expand Down Expand Up @@ -269,24 +276,25 @@ impl<'a> Iterator for CmsgIterator<'a> {
if aligned_cmsg_len > self.buf.len() {
return None;
}
let cmsg_data = &self.buf[cmsg_align(sizeof_cmsghdr)..cmsg_len];
self.buf = &self.buf[aligned_cmsg_len..];
self.next += 1;

match (cmsg.cmsg_level, cmsg.cmsg_type) {
(libc::SOL_SOCKET, libc::SCM_RIGHTS) => unsafe {
Some(ControlMessage::ScmRights(
slice::from_raw_parts(
&cmsg.cmsg_data as *const _ as *const _, 1)))
slice::from_raw_parts(cmsg_data.as_ptr() as *const _,
cmsg_data.len() / mem::size_of::<RawFd>())))
},
(libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => unsafe {
Some(ControlMessage::ScmTimestamp(
&*(&cmsg.cmsg_data as *const _ as *const _)))
&*(cmsg_data.as_ptr() as *const _)))
},
(_, _) => unsafe {
Some(ControlMessage::Unknown(UnknownCmsg(
&cmsg,
slice::from_raw_parts(
&cmsg.cmsg_data as *const _ as *const _,
cmsg_data.as_ptr() as *const _,
len))))
}
}
Expand Down Expand Up @@ -380,7 +388,7 @@ pub enum ControlMessage<'a> {
pub struct UnknownCmsg<'a>(&'a cmsghdr, &'a [u8]);

fn cmsg_align(len: usize) -> usize {
let align_bytes = mem::size_of::<type_of_cmsg_data>() - 1;
let align_bytes = mem::size_of::<align_of_cmsg_data>() - 1;
(len + align_bytes) & !align_bytes
}

Expand All @@ -405,17 +413,15 @@ impl<'a> ControlMessage<'a> {
}
}

// Unsafe: start and end of buffer must be size_t-aligned (that is,
// cmsg_align'd). Updates the provided slice; panics if the buffer
// is too small.
// Unsafe: start and end of buffer must be cmsg_align'd. Updates
// the provided slice; panics if the buffer is too small.
unsafe fn encode_into<'b>(&self, buf: &mut &'b mut [u8]) {
match *self {
ControlMessage::ScmRights(fds) => {
let cmsg = cmsghdr {
cmsg_len: self.len() as type_of_cmsg_len,
cmsg_len: self.len() as _,
cmsg_level: libc::SOL_SOCKET,
cmsg_type: libc::SCM_RIGHTS,
cmsg_data: [],
};
copy_bytes(&cmsg, buf);

Expand All @@ -431,10 +437,9 @@ impl<'a> ControlMessage<'a> {
},
ControlMessage::ScmTimestamp(t) => {
let cmsg = cmsghdr {
cmsg_len: self.len() as type_of_cmsg_len,
cmsg_len: self.len() as _,
cmsg_level: libc::SOL_SOCKET,
cmsg_type: libc::SCM_TIMESTAMP,
cmsg_data: [],
};
copy_bytes(&cmsg, buf);

Expand Down Expand Up @@ -495,15 +500,15 @@ pub fn sendmsg<'a>(fd: RawFd, iov: &[IoVec<&'a [u8]>], cmsgs: &[ControlMessage<'
};

let mhdr = msghdr {
msg_name: name as *const c_void,
msg_name: name as *mut _,
msg_namelen: namelen,
msg_iov: iov.as_ptr(),
msg_iovlen: iov.len() as type_of_msg_iovlen,
msg_control: cmsg_ptr,
msg_controllen: capacity as type_of_cmsg_len,
msg_iov: iov.as_ptr() as *mut _,
msg_iovlen: iov.len() as _,
msg_control: cmsg_ptr as *mut _,
msg_controllen: capacity as _,
msg_flags: 0,
};
let ret = unsafe { ffi::sendmsg(fd, &mhdr, flags.bits()) };
let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };

Errno::result(ret).map(|r| r as usize)
}
Expand All @@ -518,15 +523,15 @@ pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<&
None => (0 as *mut _, 0),
};
let mut mhdr = msghdr {
msg_name: &mut address as *const _ as *const c_void,
msg_name: &mut address as *mut _ as *mut _,
msg_namelen: mem::size_of::<sockaddr_storage>() as socklen_t,
msg_iov: iov.as_ptr() as *const IoVec<&[u8]>, // safe cast to add const-ness
msg_iovlen: iov.len() as type_of_msg_iovlen,
msg_control: msg_control as *const c_void,
msg_controllen: msg_controllen as type_of_cmsg_len,
msg_iov: iov.as_ptr() as *mut _,
msg_iovlen: iov.len() as _,
msg_control: msg_control as *mut _,
msg_controllen: msg_controllen as _,
msg_flags: 0,
};
let ret = unsafe { ffi::recvmsg(fd, &mut mhdr, flags.bits()) };
let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };

Ok(unsafe { RecvMsg {
bytes: try!(Errno::result(ret)) as usize,
Expand Down Expand Up @@ -743,7 +748,7 @@ pub fn connect(fd: RawFd, addr: &SockAddr) -> Result<()> {
/// [Further reading](http://man7.org/linux/man-pages/man2/recv.2.html)
pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
unsafe {
let ret = ffi::recv(
let ret = libc::recv(
sockfd,
buf.as_ptr() as *mut c_void,
buf.len() as size_t,
Expand All @@ -762,7 +767,7 @@ pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, SockAddr)> {
let addr: sockaddr_storage = mem::zeroed();
let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;

let ret = try!(Errno::result(ffi::recvfrom(
let ret = try!(Errno::result(libc::recvfrom(
sockfd,
buf.as_ptr() as *mut c_void,
buf.len() as size_t,
Expand Down

0 comments on commit b35564f

Please sign in to comment.