From 89059ee485b2eefdecc1e55daa14bcb857e6d2f1 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Sat, 13 Jun 2020 08:11:34 +0000 Subject: msg_socket: introduce UnixSeqpacketExt Occasionally, it is useful to be able to use UnixSeqpacket as a type that can represent any kind of MsgSocket. For example, to keep some MsgSockets of different types in a Vec. In this case, it may be known what type of messages should be sent over a socket, even though that may not be represantable in the type system. To accomodate this situation, this patch introduces send_msg_on_socket and recv_msg_on_socket methods on UnixSeqpacket, that can be used to send or receive any kind of MsgOnSocket. The caller is obviously responsible for ensuring that the messages being sent are of the type expected by the socket. This lack of type safety for message types is not ideal, and so MsgSender and MsgReceiver should still be preferred wherever possible. Message-Id: <20200614114344.22642-2-hi@alyssa.is> --- msg_socket/src/lib.rs | 52 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/msg_socket/src/lib.rs b/msg_socket/src/lib.rs index 540d49d..be86070 100644 --- a/msg_socket/src/lib.rs +++ b/msg_socket/src/lib.rs @@ -123,42 +123,38 @@ impl AsRawFd for Receiver { } } -/// Types that could send a message. -pub trait MsgSender: AsRef { - type M: MsgOnSocket; - fn send(&self, msg: &Self::M) -> MsgResult<()> { +pub trait UnixSeqpacketExt { + fn send_msg_on_socket(&self, msg: &M) -> MsgResult<()>; + fn recv_msg_on_socket(&self) -> MsgResult; +} + +impl UnixSeqpacketExt for UnixSeqpacket { + fn send_msg_on_socket(&self, msg: &M) -> MsgResult<()> { let msg_size = msg.msg_size(); let fd_size = msg.fd_count(); let mut msg_buffer: Vec = vec![0; msg_size]; let mut fd_buffer: Vec = vec![0; fd_size]; let fd_size = msg.write_to_buffer(&mut msg_buffer, &mut fd_buffer)?; - let sock: &UnixSeqpacket = self.as_ref(); if fd_size == 0 { - handle_eintr!(sock.send(&msg_buffer)) + handle_eintr!(self.send(&msg_buffer)) .map_err(|e| MsgError::Send(SysError::new(e.raw_os_error().unwrap_or(0))))?; } else { let ioslice = IoSlice::new(&msg_buffer[..]); - sock.send_with_fds(&[ioslice], &fd_buffer[0..fd_size]) + self.send_with_fds(&[ioslice], &fd_buffer[0..fd_size]) .map_err(MsgError::Send)?; } Ok(()) } -} - -/// Types that could receive a message. -pub trait MsgReceiver: AsRef { - type M: MsgOnSocket; - fn recv(&self) -> MsgResult { - let sock: &UnixSeqpacket = self.as_ref(); + fn recv_msg_on_socket(&self) -> MsgResult { let (msg_buffer, fd_buffer) = { - if Self::M::uses_fd() { - sock.recv_as_vec_with_fds() + if M::uses_fd() { + self.recv_as_vec_with_fds() .map_err(|e| MsgError::Recv(SysError::new(e.raw_os_error().unwrap_or(0))))? } else { ( - sock.recv_as_vec().map_err(|e| { + self.recv_as_vec().map_err(|e| { MsgError::Recv(SysError::new(e.raw_os_error().unwrap_or(0))) })?, vec![], @@ -166,11 +162,11 @@ pub trait MsgReceiver: AsRef { } }; - if msg_buffer.len() == 0 && Self::M::fixed_size() != Some(0) { + if msg_buffer.len() == 0 && M::fixed_size() != Some(0) { return Err(MsgError::RecvZero); } - if let Some(fixed_size) = Self::M::fixed_size() { + if let Some(fixed_size) = M::fixed_size() { if fixed_size != msg_buffer.len() { return Err(MsgError::BadRecvSize { expected: fixed_size, @@ -180,7 +176,7 @@ pub trait MsgReceiver: AsRef { } // Safe because fd buffer is read from socket. - let (v, read_fd_size) = unsafe { Self::M::read_from_buffer(&msg_buffer, &fd_buffer)? }; + let (v, read_fd_size) = unsafe { M::read_from_buffer(&msg_buffer, &fd_buffer)? }; if fd_buffer.len() != read_fd_size { return Err(MsgError::NotExpectFd); } @@ -188,6 +184,22 @@ pub trait MsgReceiver: AsRef { } } +/// Types that could send a message. +pub trait MsgSender: AsRef { + type M: MsgOnSocket; + fn send(&self, msg: &Self::M) -> MsgResult<()> { + self.as_ref().send_msg_on_socket(msg) + } +} + +/// Types that could receive a message. +pub trait MsgReceiver: AsRef { + type M: MsgOnSocket; + fn recv(&self) -> MsgResult { + self.as_ref().recv_msg_on_socket() + } +} + impl MsgSender for MsgSocket { type M = I; } -- cgit 1.4.1