summary refs log tree commit diff
path: root/msg_socket2/src
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2020-03-20 05:48:28 +0000
committerAlyssa Ross <hi@alyssa.is>2020-06-15 09:37:05 +0000
commit8214c4c64fbdbf6ae84634bb822a90959271cad5 (patch)
tree6d46db38cb233ae7a7cf592b485608af96accf12 /msg_socket2/src
parentb76f0d1043ffde3c6525abaecb421c0a4dc4c277 (diff)
downloadcrosvm-8214c4c64fbdbf6ae84634bb822a90959271cad5.tar
crosvm-8214c4c64fbdbf6ae84634bb822a90959271cad5.tar.gz
crosvm-8214c4c64fbdbf6ae84634bb822a90959271cad5.tar.bz2
crosvm-8214c4c64fbdbf6ae84634bb822a90959271cad5.tar.lz
crosvm-8214c4c64fbdbf6ae84634bb822a90959271cad5.tar.xz
crosvm-8214c4c64fbdbf6ae84634bb822a90959271cad5.tar.zst
crosvm-8214c4c64fbdbf6ae84634bb822a90959271cad5.zip
msg_socket2: initial commit
Diffstat (limited to 'msg_socket2/src')
-rw-r--r--msg_socket2/src/de.rs21
-rw-r--r--msg_socket2/src/error.rs23
-rw-r--r--msg_socket2/src/lib.rs34
-rw-r--r--msg_socket2/src/ser.rs20
-rw-r--r--msg_socket2/src/socket.rs48
5 files changed, 146 insertions, 0 deletions
diff --git a/msg_socket2/src/de.rs b/msg_socket2/src/de.rs
new file mode 100644
index 0000000..1d3a9e1
--- /dev/null
+++ b/msg_socket2/src/de.rs
@@ -0,0 +1,21 @@
+use serde::Deserializer;
+use std::os::unix::prelude::*;
+
+pub trait DeserializeWithFds<'de>: Sized {
+    fn deserialize<I, De>(deserializer: DeserializerWithFds<I, De>) -> Result<Self, De::Error>
+    where
+        I: Iterator<Item = RawFd>,
+        De: Deserializer<'de>;
+}
+
+#[derive(Debug)]
+pub struct DeserializerWithFds<'iter, Iter, De> {
+    pub deserializer: De,
+    pub fds: &'iter mut Iter,
+}
+
+impl<'iter, Iter, De> DeserializerWithFds<'iter, Iter, De> {
+    pub fn new(fds: &'iter mut Iter, deserializer: De) -> Self {
+        Self { deserializer, fds }
+    }
+}
diff --git a/msg_socket2/src/error.rs b/msg_socket2/src/error.rs
new file mode 100644
index 0000000..902684b
--- /dev/null
+++ b/msg_socket2/src/error.rs
@@ -0,0 +1,23 @@
+#[derive(Debug)]
+pub enum Error {
+    DataError(bincode::Error),
+    IoError(sys_util::Error),
+}
+
+impl From<bincode::Error> for Error {
+    fn from(error: bincode::Error) -> Self {
+        Self::DataError(error)
+    }
+}
+
+impl From<sys_util::Error> for Error {
+    fn from(error: sys_util::Error) -> Self {
+        Self::IoError(error)
+    }
+}
+
+impl From<std::io::Error> for Error {
+    fn from(error: std::io::Error) -> Self {
+        Self::IoError(error.into())
+    }
+}
diff --git a/msg_socket2/src/lib.rs b/msg_socket2/src/lib.rs
new file mode 100644
index 0000000..748a9f7
--- /dev/null
+++ b/msg_socket2/src/lib.rs
@@ -0,0 +1,34 @@
+// Copyright 2020, Alyssa Ross
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of the <organization> nor the
+//       names of its contributors may be used to endorse or promote products
+//       derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+mod de;
+mod error;
+mod ser;
+mod socket;
+
+pub use de::{DeserializeWithFds, DeserializerWithFds};
+pub use error::Error;
+pub use ser::{SerializeWithFds, SerializerWithFds};
+pub use socket::Socket;
diff --git a/msg_socket2/src/ser.rs b/msg_socket2/src/ser.rs
new file mode 100644
index 0000000..0a60ea8
--- /dev/null
+++ b/msg_socket2/src/ser.rs
@@ -0,0 +1,20 @@
+use serde::Serializer;
+use std::os::unix::prelude::*;
+
+pub trait SerializeWithFds {
+    fn serialize<Ser>(&self, serializer: SerializerWithFds<Ser>) -> Result<Ser::Ok, Ser::Error>
+    where
+        Ser: Serializer;
+}
+
+#[derive(Debug)]
+pub struct SerializerWithFds<'fds, Ser> {
+    pub serializer: Ser,
+    pub fds: &'fds mut Vec<RawFd>,
+}
+
+impl<'fds, Ser> SerializerWithFds<'fds, Ser> {
+    pub fn new(fds: &'fds mut Vec<RawFd>, serializer: Ser) -> Self {
+        Self { serializer, fds }
+    }
+}
diff --git a/msg_socket2/src/socket.rs b/msg_socket2/src/socket.rs
new file mode 100644
index 0000000..bce587a
--- /dev/null
+++ b/msg_socket2/src/socket.rs
@@ -0,0 +1,48 @@
+use bincode::{DefaultOptions, Serializer, Deserializer};
+use std::marker::PhantomData;
+use std::io::IoSlice;
+use sys_util::{net::UnixSeqpacket, ScmSocket};
+
+use crate::{DeserializerWithFds, DeserializeWithFds, Error, SerializeWithFds, SerializerWithFds};
+
+#[derive(Debug)]
+pub struct Socket<Send, Recv> {
+    sock: UnixSeqpacket,
+    __: PhantomData<(Send, Recv)>,
+}
+
+impl<Send, Recv> Socket<Send, Recv> {
+    pub fn new(sock: UnixSeqpacket) -> Self {
+        Self {
+            sock,
+            __: PhantomData,
+        }
+    }
+}
+
+impl<Send: SerializeWithFds, Recv> Socket<Send, Recv> {
+    pub fn send(&self, value: Send) -> Result<(), Error> {
+        let mut bytes: Vec<u8> = vec![];
+        let mut fds: Vec<RawFd> = vec![];
+
+        let mut serializer = Serializer::new(&mut bytes, DefaultOptions::new());
+        let serializer_with_fds = SerializerWithFds::new(&mut fds, &mut serializer);
+        value.serialize(serializer_with_fds)?;
+
+        self.sock.send_with_fds(&[IoSlice::new(&bytes)], &fds)?;
+
+        Ok(())
+    }
+}
+
+impl<Send, Recv: for<'de> DeserializeWithFds<'de>> Socket<Send, Recv> {
+    pub fn recv(&self) -> Result<Recv, Error> {
+        let (bytes, fds) = self.sock.recv_as_vec_with_fds()?;
+        let mut fds_iter = fds.into_iter();
+
+        let mut deserializer = Deserializer::from_slice(&bytes, DefaultOptions::new());
+        let deserializer_with_fds = DeserializerWithFds::new(&mut fds_iter, &mut deserializer);
+
+        Ok(Recv::deserialize(deserializer_with_fds)?)
+    }
+}