Parcourir la source

Started working on a messaging module.

Matthew Carr il y a 2 ans
Parent
commit
5c883847b1
6 fichiers modifiés avec 318 ajouts et 13 suppressions
  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",
  "log",
  "nix",
  "nix",
  "openssl",
  "openssl",
+ "os_pipe",
  "serde",
  "serde",
  "serde-big-array",
  "serde-big-array",
  "static_assertions",
  "static_assertions",
@@ -147,6 +148,7 @@ dependencies = [
  "tempdir",
  "tempdir",
  "tss-esapi",
  "tss-esapi",
  "tss-esapi-sys",
  "tss-esapi-sys",
+ "zerocopy",
  "zeroize",
  "zeroize",
 ]
 ]
 
 
@@ -169,6 +171,12 @@ dependencies = [
  "serde-big-array",
  "serde-big-array",
 ]
 ]
 
 
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
 [[package]]
 [[package]]
 name = "cc"
 name = "cc"
 version = "1.0.73"
 version = "1.0.73"
@@ -527,6 +535,16 @@ dependencies = [
  "vcpkg",
  "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]]
 [[package]]
 name = "peeking_take_while"
 name = "peeking_take_while"
 version = "0.1.2"
 version = "0.1.2"
@@ -990,6 +1008,27 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 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]]
 [[package]]
 name = "zeroize"
 name = "zeroize"
 version = "1.5.7"
 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"] }
 zeroize = { version = "1.5.7", features = ["zeroize_derive"] }
 static_assertions = "1.1.0"
 static_assertions = "1.1.0"
 brotli = "3.3.4"
 brotli = "3.3.4"
+os_pipe = { version = "1.1.1", features = ["io_safety"] }
+zerocopy = "0.6.1"
 
 
 [dev-dependencies]
 [dev-dependencies]
 tempdir = "0.3.7"
 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
 - 13
 Change the Hash enum so it contains structs for each hash type. Unify these structs with the node
 Change the Hash enum so it contains structs for each hash type. Unify these structs with the node
 structs used in the VecMerkleTree.
 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;
 mod block_path;
 pub use block_path::{BlockPath, BlockPathError};
 pub use block_path::{BlockPath, BlockPathError};
-mod sectored_buf;
-mod trailered;
 /// Code which enables cryptographic operations.
 /// Code which enables cryptographic operations.
 pub mod crypto;
 pub mod crypto;
+pub mod msg;
+mod sectored_buf;
+mod trailered;
 
 
 #[cfg(test)]
 #[cfg(test)]
 mod test_helpers;
 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(())
         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> {
     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])
         Ok(buf[0])
     }
     }
 
 
     fn read_u16(&mut self) -> Result<u16> {
     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))
         Ok(u16::from_le_bytes(buf))
     }
     }
 
 
     fn read_u32(&mut self) -> Result<u32> {
     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))
         Ok(u32::from_le_bytes(buf))
     }
     }
 
 
     fn read_u64(&mut self) -> Result<u64> {
     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))
         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> {
     fn read_i8(&mut self) -> Result<i8> {
         let value = self.read_u8()?;
         let value = self.read_u8()?;
         Ok(value as i8)
         Ok(value as i8)
@@ -131,6 +138,16 @@ impl<'de, T: Read + ?Sized> Deserializer<'de, T> {
         Ok(value as i32)
         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> {
     fn read_bool(&mut self) -> Result<bool> {
         let byte = self.read_u8()?;
         let byte = self.read_u8()?;
         Ok(byte > 0)
         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> {
     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> {
     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)
         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> {
     fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
         let mut buf = [0u8; 4];
         let mut buf = [0u8; 4];
         self.read_exact(&mut buf)?;
         self.read_exact(&mut buf)?;
@@ -493,6 +519,17 @@ mod test {
         Ok(())
         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]
     #[test]
     fn deserialize_u8() -> Result<()> {
     fn deserialize_u8() -> Result<()> {
         let vec: Vec<u8> = vec![0xFF];
         let vec: Vec<u8> = vec![0xFF];
@@ -525,6 +562,17 @@ mod test {
         Ok(())
         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]
     #[test]
     fn deserialize_f32() -> Result<()> {
     fn deserialize_f32() -> Result<()> {
         let vec: Vec<u8> = vec![0x00, 0x00, 0x20, 0x3E];
         let vec: Vec<u8> = vec![0x00, 0x00, 0x20, 0x3E];