about summary refs log tree commit diff
path: root/library/std/src/sys/unix/net.rs
diff options
context:
space:
mode:
authorLinkTed <LinkTed@users.noreply.github.com>2020-08-21 14:52:10 +0200
committerLinkTed <LinkTed@users.noreply.github.com>2020-10-10 15:19:11 +0200
commit0b3c9d84656a86cb3c57b20fff6bef5f8f2aeabb (patch)
tree207a6b906cc54da6e01bfc7b83715cd7ffb5c406 /library/std/src/sys/unix/net.rs
parent7477d445c8b2e942f5cc745fae0e3233494e7460 (diff)
downloadrust-0b3c9d84656a86cb3c57b20fff6bef5f8f2aeabb.tar.gz
rust-0b3c9d84656a86cb3c57b20fff6bef5f8f2aeabb.zip
unix: Extend UnixStream and UnixDatagram to send and receive file descriptors
Add the functions `recv_vectored_fds` and `send_vectored_fds` to send and receive file descriptors, by using `recvmsg` and `sendmsg` system call.
Diffstat (limited to 'library/std/src/sys/unix/net.rs')
-rw-r--r--library/std/src/sys/unix/net.rs92
1 files changed, 92 insertions, 0 deletions
diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs
index 011325fddc5..e067edd3774 100644
--- a/library/std/src/sys/unix/net.rs
+++ b/library/std/src/sys/unix/net.rs
@@ -1,8 +1,10 @@
 use crate::cmp;
 use crate::ffi::CStr;
 use crate::io::{self, IoSlice, IoSliceMut};
+use crate::marker::PhantomData;
 use crate::mem;
 use crate::net::{Shutdown, SocketAddr};
+use crate::ptr::null_mut;
 use crate::str;
 use crate::sys::fd::FileDesc;
 use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr};
@@ -18,6 +20,86 @@ pub extern crate libc as netc;
 
 pub type wrlen_t = size_t;
 
+pub struct AncillaryDataIter<'a, T> {
+    data: &'a [u8],
+    phantom: crate::marker::PhantomData<T>,
+}
+
+impl<'a, T> AncillaryDataIter<'a, T> {
+    pub fn new(data: &'a [u8]) -> AncillaryDataIter<'a, T> {
+        AncillaryDataIter { data, phantom: PhantomData }
+    }
+}
+
+impl<'a, T> Iterator for AncillaryDataIter<'a, T> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        unsafe {
+            let mut unit = mem::zeroed();
+            if mem::size_of::<T>() <= self.data.len() {
+                let unit_ptr: *mut T = &mut unit;
+                libc::memcpy(unit_ptr.cast(), self.data.as_ptr().cast(), mem::size_of::<T>());
+                self.data = &self.data[mem::size_of::<T>()..];
+                Some(unit)
+            } else {
+                None
+            }
+        }
+    }
+}
+
+pub fn add_to_ancillary_data<T: core::clone::Clone>(
+    buffer: &mut [u8],
+    length: &mut usize,
+    source: &[T],
+    cmsg_level: libc::c_int,
+    cmsg_type: libc::c_int,
+) -> bool {
+    let len = (source.len() * mem::size_of::<T>()) as u32;
+
+    unsafe {
+        let additional_space = libc::CMSG_SPACE(len) as usize;
+        if *length + additional_space > buffer.len() {
+            return false;
+        }
+
+        libc::memset(buffer[*length..].as_mut_ptr().cast(), 0, additional_space);
+
+        *length += additional_space;
+
+        let msg = libc::msghdr {
+            msg_name: null_mut(),
+            msg_namelen: 0,
+            msg_iov: null_mut(),
+            msg_iovlen: 0,
+            msg_control: buffer.as_mut_ptr().cast(),
+            msg_controllen: *length,
+            msg_flags: 0,
+        };
+
+        let mut cmsg = libc::CMSG_FIRSTHDR(&msg);
+        let mut previous_cmsg = cmsg;
+        while !cmsg.is_null() {
+            previous_cmsg = cmsg;
+            cmsg = libc::CMSG_NXTHDR(&msg, cmsg);
+        }
+
+        if previous_cmsg.is_null() {
+            return false;
+        }
+
+        (*previous_cmsg).cmsg_level = cmsg_level;
+        (*previous_cmsg).cmsg_type = cmsg_type;
+        (*previous_cmsg).cmsg_len = libc::CMSG_LEN(len) as usize;
+
+        let data = libc::CMSG_DATA(previous_cmsg).cast();
+
+        libc::memcpy(data, source.as_ptr().cast(), len as usize);
+    }
+    true
+}
+
 pub struct Socket(FileDesc);
 
 pub fn init() {}
@@ -237,6 +319,11 @@ impl Socket {
         self.recv_from_with_flags(buf, 0)
     }
 
+    pub fn recv_msg(&self, msg: &mut libc::msghdr) -> io::Result<usize> {
+        let n = cvt(unsafe { libc::recvmsg(self.0.raw(), msg, libc::MSG_CMSG_CLOEXEC) })?;
+        Ok(n as usize)
+    }
+
     pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
         self.recv_from_with_flags(buf, MSG_PEEK)
     }
@@ -254,6 +341,11 @@ impl Socket {
         self.0.is_write_vectored()
     }
 
+    pub fn send_msg(&self, msg: &mut libc::msghdr) -> io::Result<usize> {
+        let n = cvt(unsafe { libc::sendmsg(self.0.raw(), msg, 0) })?;
+        Ok(n as usize)
+    }
+
     pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
         let timeout = match dur {
             Some(dur) => {