[][src]Enum nix::sys::socket::ControlMessage

pub enum ControlMessage<'a> {
    ScmRights(&'a [RawFd]),
    ScmCredentials(&'a ucred),
    ScmTimestamp(&'a TimeVal),
    // some variants omitted
}

A type-safe wrapper around a single control message. More types may be added to this enum; do not exhaustively pattern-match it. Further reading

Variants

ScmRights(&'a [RawFd])

A message of type SCM_RIGHTS, containing an array of file descriptors passed between processes.

See the description in the "Ancillary messages" section of the unix(7) man page.

Using multiple ScmRights messages for a single sendmsg call isn't recommended since it causes platform-dependent behaviour: It might swallow all but the first ScmRights message or fail with EINVAL. Instead, you can put all fds to be passed into a single ScmRights message.

ScmCredentials(&'a ucred)

A message of type SCM_CREDENTIALS, containing the pid, uid and gid of a process connected to the socket.

This is similar to the socket option SO_PEERCRED, but requires a process to explicitly send its credentials. A process running as root is allowed to specify any credentials, while credentials sent by other processes are verified by the kernel.

For further information, please refer to the unix(7) man page.

ScmTimestamp(&'a TimeVal)

A message of type SCM_TIMESTAMP, containing the time the packet was received by the kernel.

See the kernel's explanation in "SO_TIMESTAMP" of networking/timestamping.

Examples

use nix::sys::socket::*;
use nix::sys::uio::IoVec;
use nix::sys::time::*;
use std::time::*;

// Set up
let message1 = "Ohayō!".as_bytes();
let message2 = "Jā ne".as_bytes();
let in_socket = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap();
setsockopt(in_socket, sockopt::ReceiveTimestamp, &true).unwrap();
bind(in_socket, &SockAddr::new_inet(InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0))).unwrap();
let address = if let Ok(address) = getsockname(in_socket) { address } else { unreachable!() };

// Send both
assert!(Ok(message1.len()) == sendmsg(in_socket, &[IoVec::from_slice(message1)], &[], MsgFlags::empty(), Some(&address)));
let time = SystemTime::now();
std::thread::sleep(Duration::from_millis(250));
assert!(Ok(message2.len()) == sendmsg(in_socket, &[IoVec::from_slice(message2)], &[], MsgFlags::empty(), Some(&address)));
let delay = time.elapsed().unwrap();

// Receive the first
let mut buffer1 = vec![0u8; message1.len() + message2.len()];
let mut time1: CmsgSpace<TimeVal> = CmsgSpace::new();
let received1 = recvmsg(in_socket, &[IoVec::from_mut_slice(&mut buffer1)], Some(&mut time1), MsgFlags::empty()).unwrap();
let mut time1 = if let Some(ControlMessage::ScmTimestamp(&time1)) = received1.cmsgs().next() { time1 } else { panic!("Unexpected or no control message") };

// Receive the second
let mut buffer2 = vec![0u8; message1.len() + message2.len()];
let mut time2: CmsgSpace<TimeVal> = CmsgSpace::new();
let received2 = recvmsg(in_socket, &[IoVec::from_mut_slice(&mut buffer2)], Some(&mut time2), MsgFlags::empty()).unwrap();
let mut time2 = if let Some(ControlMessage::ScmTimestamp(&time2)) = received2.cmsgs().next() { time2 } else { panic!("Unexpected or no control message") };

// Swap if needed; UDP is unordered
match (received1.bytes, received2.bytes, message1.len(), message2.len()) {
    (l1, l2, m1, m2) if l1 == m1 && l2 == m2 => {},
    (l2, l1, m1, m2) if l1 == m1 && l2 == m2 => {
        std::mem::swap(&mut time1, &mut time2);
        std::mem::swap(&mut buffer1, &mut buffer2);
    },
    _ => panic!("Wrong packets"),
};

// Compare results
println!("{:?} @ {:?}, {:?} @ {:?}, {:?}", buffer1, time1, buffer2, time2, delay);
assert!(message1 == &buffer1[0..(message1.len())], "{:?} == {:?}", message1, buffer1);
assert!(message2 == &buffer2[0..(message2.len())], "{:?} == {:?}", message2, buffer2);
let time = time2 - time1;
let time = Duration::new(time.num_seconds() as u64, time.num_nanoseconds() as u32);
let difference = if delay < time { time - delay } else { delay - time };
assert!(difference.subsec_nanos() < 5_000_000, "{}ns < 5ms", difference.subsec_nanos());
assert!(difference.as_secs() == 0);

// Close socket
nix::unistd::close(in_socket).unwrap();

Auto Trait Implementations

impl<'a> Send for ControlMessage<'a>

impl<'a> Sync for ControlMessage<'a>

Blanket Implementations

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> From<T> for T[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> Any for T where
    T: 'static + ?Sized
[src]