[−][src]Enum nix::sys::socket::ControlMessage
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]
U: From<T>,
impl<T> From<T> for T
[src]
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
[src]
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,