Browse Source

Started working on a messaging module.

Matthew Carr 2 years ago
parent
commit
5c883847b1
6 changed files with 318 additions and 13 deletions
  1. 39 0
      Cargo.lock
  2. 2 0
      crates/btlib/Cargo.toml
  3. 3 0
      crates/btlib/TODO.txt
  4. 3 2
      crates/btlib/src/lib.rs
  5. 212 0
      crates/btlib/src/msg.rs
  6. 59 11
      crates/btserde/src/de.rs

+ 39 - 0
Cargo.lock

@@ -139,6 +139,7 @@ dependencies = [
  "log",
  "nix",
  "openssl",
+ "os_pipe",
  "serde",
  "serde-big-array",
  "static_assertions",
@@ -147,6 +148,7 @@ dependencies = [
  "tempdir",
  "tss-esapi",
  "tss-esapi-sys",
+ "zerocopy",
  "zeroize",
 ]
 
@@ -169,6 +171,12 @@ dependencies = [
  "serde-big-array",
 ]
 
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
 [[package]]
 name = "cc"
 version = "1.0.73"
@@ -527,6 +535,16 @@ dependencies = [
  "vcpkg",
 ]
 
+[[package]]
+name = "os_pipe"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dceb7e43f59c35ee1548045b2c72945a5a3bb6ce6d6f07cdc13dc8f6bc4930a"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
 [[package]]
 name = "peeking_take_while"
 version = "0.1.2"
@@ -990,6 +1008,27 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
+[[package]]
+name = "zerocopy"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6505e6815af7de1746a08f69c69606bb45695a17149517680f3b2149713b19a3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "zeroize"
 version = "1.5.7"

+ 2 - 0
crates/btlib/Cargo.toml

@@ -22,6 +22,8 @@ foreign-types = "0.3.1"
 zeroize = { version = "1.5.7", features = ["zeroize_derive"] }
 static_assertions = "1.1.0"
 brotli = "3.3.4"
+os_pipe = { version = "1.1.1", features = ["io_safety"] }
+zerocopy = "0.6.1"
 
 [dev-dependencies]
 tempdir = "0.3.7"

+ 3 - 0
crates/btlib/TODO.txt

@@ -38,3 +38,6 @@ be codified by a trait to allow the implementation to be changed in the future.
 - 13
 Change the Hash enum so it contains structs for each hash type. Unify these structs with the node
 structs used in the VecMerkleTree.
+
+- 14, 13, mdcarr941@gmail.com, 58d1f6, 
+Create a new crate which implements a FUSE daemon.

+ 3 - 2
crates/btlib/src/lib.rs

@@ -1,9 +1,10 @@
 mod block_path;
 pub use block_path::{BlockPath, BlockPathError};
-mod sectored_buf;
-mod trailered;
 /// Code which enables cryptographic operations.
 pub mod crypto;
+pub mod msg;
+mod sectored_buf;
+mod trailered;
 
 #[cfg(test)]
 mod test_helpers;

+ 212 - 0
crates/btlib/src/msg.rs

@@ -0,0 +1,212 @@
+//! Code which enables sending messages between processes in the blocktree system.
+
+pub use private::*;
+
+mod private {
+    use crate::{crypto::rand_array, BlockPath, Result, Writecap};
+    use btserde::{read_from, write_to};
+    use os_pipe::{PipeReader, PipeWriter};
+    use serde::{Deserialize, Serialize};
+    use std::io::{Read, Write};
+    use zerocopy::FromBytes;
+
+    #[derive(PartialEq, Eq, Serialize, Deserialize)]
+    pub enum MsgError {}
+
+    #[derive(Serialize, Deserialize)]
+    pub enum MsgBody {
+        Success,
+        Fail(MsgError),
+        Ping,
+        Hello(Writecap),
+        Read { offset: u64 },
+        Write { offset: u64, data: Vec<u8> },
+        Custom(Vec<u8>),
+    }
+
+    #[derive(Serialize, Deserialize)]
+    pub struct Msg {
+        from: BlockPath,
+        to: BlockPath,
+        id: u128,
+        body: MsgBody,
+    }
+
+    impl Msg {
+        pub fn from(&self) -> &BlockPath {
+            &self.from
+        }
+
+        pub fn to(&self) -> &BlockPath {
+            &self.to
+        }
+
+        pub fn id(&self) -> u128 {
+            self.id
+        }
+
+        pub fn body(&self) -> &MsgBody {
+            &self.body
+        }
+    }
+
+    #[derive(Serialize, Deserialize)]
+    pub enum VerMsg {
+        V0(Msg),
+    }
+
+    pub trait Sender: Send {
+        fn send(&mut self, msg: Msg) -> Result<()>;
+        fn path(&self) -> &BlockPath;
+
+        /// Generates and returns a new message ID.
+        fn gen_id(&mut self) -> Result<u128> {
+            const LEN: usize = std::mem::size_of::<u128>();
+            let bytes = rand_array::<LEN>()?;
+            let option = u128::read_from(bytes.as_slice());
+            // Safety: because LEN == size_of::<u128>(), read_from should have returned Some.
+            Ok(option.unwrap())
+        }
+
+        /// This is a convenience method which creates a new message, addresses it to the given
+        /// path, sets it as from this sender's path, generates a new ID for it, puts the given
+        /// body inside of it, and dispatches it with the `send` method.
+        fn send_new(&mut self, to: BlockPath, body: MsgBody) -> Result<()> {
+            let id = self.gen_id()?;
+            let msg = Msg {
+                to,
+                from: self.path().to_owned(),
+                id,
+                body,
+            };
+            self.send(msg)
+        }
+    }
+
+    pub trait Receiver {
+        fn receive(&mut self) -> Result<Msg>;
+        fn path(&self) -> &BlockPath;
+    }
+
+    pub trait Channel {
+        type Sender: Sender;
+        type Receiver: Receiver;
+
+        fn new(path: BlockPath) -> Result<(Self::Sender, Self::Receiver)>;
+    }
+
+    pub trait Router {
+        fn add_sender<S: Sender>(&mut self, sender: S) -> Result<()>;
+        fn send(&mut self, msg: Msg) -> Result<()>;
+    }
+
+    trait TryClone<O> {
+        fn try_clone(&self) -> Result<O>;
+    }
+
+    impl TryClone<PipeWriter> for PipeWriter {
+        fn try_clone(&self) -> Result<PipeWriter> {
+            Ok(PipeWriter::try_clone(&self)?)
+        }
+    }
+
+    pub struct WriteSender<W> {
+        write: W,
+        path: BlockPath,
+    }
+
+    impl<W: Write + Send> Sender for WriteSender<W> {
+        fn send(&mut self, msg: Msg) -> Result<()> {
+            Ok(write_to(&msg, &mut self.write)?)
+        }
+
+        fn path(&self) -> &BlockPath {
+            &self.path
+        }
+    }
+
+    impl<W: Write + TryClone<W>> TryClone<WriteSender<W>> for WriteSender<W> {
+        fn try_clone(&self) -> Result<WriteSender<W>> {
+            Ok(WriteSender {
+                write: self.write.try_clone()?,
+                path: self.path.clone(),
+            })
+        }
+    }
+
+    pub struct ReadReceiver<R> {
+        read: R,
+        path: BlockPath,
+    }
+
+    impl<R: Read> Receiver for ReadReceiver<R> {
+        fn receive(&mut self) -> Result<Msg> {
+            Ok(read_from(&mut self.read)?)
+        }
+
+        fn path(&self) -> &BlockPath {
+            &self.path
+        }
+    }
+
+    pub enum PipeChannel {}
+
+    impl Channel for PipeChannel {
+        type Sender = WriteSender<PipeWriter>;
+        type Receiver = ReadReceiver<PipeReader>;
+
+        fn new(path: BlockPath) -> Result<(Self::Sender, Self::Receiver)> {
+            let (read, write) = os_pipe::pipe()?;
+            let sender = WriteSender {
+                path: path.clone(),
+                write,
+            };
+            let receiver = ReadReceiver { path, read };
+            Ok((sender, receiver))
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::test_helpers;
+
+    use super::*;
+
+    #[test]
+    fn ping_pong_via_pipes() {
+        let ping_path = test_helpers::make_path(vec!["ping"]);
+        let (mut ping_sender, mut ping_receiver) =
+            PipeChannel::new(ping_path.clone()).expect("failed to create a ping channel");
+        let pong_path = test_helpers::make_path(vec!["pong"]);
+        let (mut pong_sender, mut pong_receiver) =
+            PipeChannel::new(pong_path.clone()).expect("failed to create a pong channel");
+        let pong = std::thread::spawn(move || loop {
+            let msg = pong_receiver.receive().expect("pong receive failed");
+            assert_eq!(pong_receiver.path(), msg.to());
+            match msg.body() {
+                MsgBody::Ping => ping_sender
+                    .send_new(ping_path.clone(), MsgBody::Success)
+                    .expect("send to ping failed"),
+                MsgBody::Success => return,
+                _ => panic!("unexpected message received by pong"),
+            }
+        });
+        let mut iter = 5;
+        while iter > 0 {
+            pong_sender
+                .send_new(pong_path.clone(), MsgBody::Ping)
+                .expect("send to pong failed");
+            let msg = ping_receiver.receive().expect("ping receive failed");
+            assert_eq!(ping_receiver.path(), msg.to());
+            match msg.body() {
+                MsgBody::Success => iter -= 1,
+                _ => panic!("unexpected message received by ping"),
+            }
+        }
+        pong_sender
+            .send_new(pong_path.clone(), MsgBody::Success)
+            .expect("send success to pong failed");
+        pong.join().expect("join failed");
+    }
+}

+ 59 - 11
crates/btserde/src/de.rs

@@ -92,30 +92,37 @@ impl<'de, T: Read + ?Sized> Deserializer<'de, T> {
         Ok(())
     }
 
+    fn read_array<const N: usize>(&mut self) -> Result<[u8; N]> {
+        let mut array = [0u8; N];
+        self.read_exact(array.as_mut_slice())?;
+        Ok(array)
+    }
+
     fn read_u8(&mut self) -> Result<u8> {
-        let mut buf = [0u8; 1];
-        self.read_exact(&mut buf)?;
+        let buf = self.read_array::<1>()?;
         Ok(buf[0])
     }
 
     fn read_u16(&mut self) -> Result<u16> {
-        let mut buf = [0u8; 2];
-        self.read_exact(&mut buf)?;
+        let buf = self.read_array()?;
         Ok(u16::from_le_bytes(buf))
     }
 
     fn read_u32(&mut self) -> Result<u32> {
-        let mut buf = [0u8; 4];
-        self.read_exact(&mut buf)?;
+        let buf = self.read_array()?;
         Ok(u32::from_le_bytes(buf))
     }
 
     fn read_u64(&mut self) -> Result<u64> {
-        let mut buf = [0u8; 8];
-        self.read_exact(&mut buf)?;
+        let buf = self.read_array()?;
         Ok(u64::from_le_bytes(buf))
     }
 
+    fn read_u128(&mut self) -> Result<u128> {
+        let buf = self.read_array()?;
+        Ok(u128::from_le_bytes(buf))
+    }
+
     fn read_i8(&mut self) -> Result<i8> {
         let value = self.read_u8()?;
         Ok(value as i8)
@@ -131,6 +138,16 @@ impl<'de, T: Read + ?Sized> Deserializer<'de, T> {
         Ok(value as i32)
     }
 
+    fn read_i64(&mut self) -> Result<i64> {
+        let value = self.read_u64()?;
+        Ok(value as i64)
+    }
+
+    fn read_i128(&mut self) -> Result<i128> {
+        let value = self.read_u128()?;
+        Ok(value as i128)
+    }
+
     fn read_bool(&mut self) -> Result<bool> {
         let byte = self.read_u8()?;
         Ok(byte > 0)
@@ -180,9 +197,13 @@ impl<'de, 'a, T: Read> de::Deserializer<'de> for &'a mut Deserializer<'de, T> {
     }
 
     fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
-        let unsigned = self.read_u64()?;
-        let signed = unsigned as i64;
-        visitor.visit_i64(signed)
+        let value = self.read_i64()?;
+        visitor.visit_i64(value)
+    }
+
+    fn deserialize_i128<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
+        let value = self.read_i128()?;
+        visitor.visit_i128(value)
     }
 
     fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
@@ -205,6 +226,11 @@ impl<'de, 'a, T: Read> de::Deserializer<'de> for &'a mut Deserializer<'de, T> {
         visitor.visit_u64(value)
     }
 
+    fn deserialize_u128<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
+        let value = self.read_u128()?;
+        visitor.visit_u128(value)
+    }
+
     fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
         let mut buf = [0u8; 4];
         self.read_exact(&mut buf)?;
@@ -493,6 +519,17 @@ mod test {
         Ok(())
     }
 
+    #[test]
+    fn deserialize_i128() -> Result<()> {
+        let vec: Vec<u8> = vec![
+            0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+            0xFF, 0xFF,
+        ];
+        let result = from_vec(&vec);
+        assert_eq!(-2i128, result?);
+        Ok(())
+    }
+
     #[test]
     fn deserialize_u8() -> Result<()> {
         let vec: Vec<u8> = vec![0xFF];
@@ -525,6 +562,17 @@ mod test {
         Ok(())
     }
 
+    #[test]
+    fn deserialize_u128() -> Result<()> {
+        let vec: Vec<u8> = vec![
+            0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+            0xFF, 0xFF,
+        ];
+        let result = from_vec(&vec);
+        assert_eq!(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEu128, result?);
+        Ok(())
+    }
+
     #[test]
     fn deserialize_f32() -> Result<()> {
         let vec: Vec<u8> = vec![0x00, 0x00, 0x20, 0x3E];