summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2020-06-13 08:11:34 +0000
committerAlyssa Ross <hi@alyssa.is>2020-06-15 08:33:04 +0000
commit89059ee485b2eefdecc1e55daa14bcb857e6d2f1 (patch)
tree5d5f3d836c0439d9dbab5c828848c84deced67b5
parenteca4902ece142985f3fb2a16651d15d6dbf9b24b (diff)
downloadcrosvm-89059ee485b2eefdecc1e55daa14bcb857e6d2f1.tar
crosvm-89059ee485b2eefdecc1e55daa14bcb857e6d2f1.tar.gz
crosvm-89059ee485b2eefdecc1e55daa14bcb857e6d2f1.tar.bz2
crosvm-89059ee485b2eefdecc1e55daa14bcb857e6d2f1.tar.lz
crosvm-89059ee485b2eefdecc1e55daa14bcb857e6d2f1.tar.xz
crosvm-89059ee485b2eefdecc1e55daa14bcb857e6d2f1.tar.zst
crosvm-89059ee485b2eefdecc1e55daa14bcb857e6d2f1.zip
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>
Notes
Reviewed-by: Cole Helbling <cole.e.helbling@outlook.com>
-rw-r--r--msg_socket/src/lib.rs52
1 files 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<M: MsgOnSocket> AsRawFd for Receiver<M> {
     }
 }
 
-/// Types that could send a message.
-pub trait MsgSender: AsRef<UnixSeqpacket> {
-    type M: MsgOnSocket;
-    fn send(&self, msg: &Self::M) -> MsgResult<()> {
+pub trait UnixSeqpacketExt {
+    fn send_msg_on_socket<M: MsgOnSocket>(&self, msg: &M) -> MsgResult<()>;
+    fn recv_msg_on_socket<M: MsgOnSocket>(&self) -> MsgResult<M>;
+}
+
+impl UnixSeqpacketExt for UnixSeqpacket {
+    fn send_msg_on_socket<M: MsgOnSocket>(&self, msg: &M) -> MsgResult<()> {
         let msg_size = msg.msg_size();
         let fd_size = msg.fd_count();
         let mut msg_buffer: Vec<u8> = vec![0; msg_size];
         let mut fd_buffer: Vec<RawFd> = 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<UnixSeqpacket> {
-    type M: MsgOnSocket;
-    fn recv(&self) -> MsgResult<Self::M> {
-        let sock: &UnixSeqpacket = self.as_ref();
 
+    fn recv_msg_on_socket<M: MsgOnSocket>(&self) -> MsgResult<M> {
         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<UnixSeqpacket> {
             }
         };
 
-        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<UnixSeqpacket> {
         }
 
         // 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<UnixSeqpacket> {
     }
 }
 
+/// Types that could send a message.
+pub trait MsgSender: AsRef<UnixSeqpacket> {
+    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<UnixSeqpacket> {
+    type M: MsgOnSocket;
+    fn recv(&self) -> MsgResult<Self::M> {
+        self.as_ref().recv_msg_on_socket()
+    }
+}
+
 impl<I: MsgOnSocket, O: MsgOnSocket> MsgSender for MsgSocket<I, O> {
     type M = I;
 }