diff options
| author | Will Dillon <william@housedillon.com> | 2025-11-06 08:41:29 +0000 |
|---|---|---|
| committer | Will Dillon <william@housedillon.com> | 2025-11-06 08:41:29 +0000 |
| commit | 92883a366651ef3973f4de9fde2e3f9654502d32 (patch) | |
| tree | 3379aee9fd8e1f6bf9c5dae6714de95b5c5afe5d /src | |
| parent | 2/3 of packets pass tests (diff) | |
| download | meshcore-rs-92883a366651ef3973f4de9fde2e3f9654502d32.tar.gz meshcore-rs-92883a366651ef3973f4de9fde2e3f9654502d32.zip | |
All the packet types pass tests
Diffstat (limited to 'src')
| -rw-r--r-- | src/crypto.rs | 1 | ||||
| -rw-r--r-- | src/packet.rs | 158 |
2 files changed, 141 insertions, 18 deletions
diff --git a/src/crypto.rs b/src/crypto.rs index e3b2917..71c1cb3 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -7,6 +7,7 @@ use x25519_dalek::StaticSecret; use hex::decode; +#[derive(Debug)] pub enum MeshcoreCryptoError { KeyLengthError, TryFromSliceError diff --git a/src/packet.rs b/src/packet.rs index 269835a..ad79688 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -63,7 +63,8 @@ impl From<u8> for PayloadVersion { } } -#[derive(PartialEq, Debug, Clone)] +#[derive(PartialEq, Debug, Clone, Difference)] +#[difference(expose)] enum PacketContent { Request(Request), Response(Response), @@ -201,11 +202,7 @@ struct Text { impl From<Bytes> for Text { fn from(value: Bytes) -> Self { - let mut text = Text { - cipher: PeerToPeerCipher::from(value) - }; - - text + Text { cipher: PeerToPeerCipher::from(value) } } } @@ -345,20 +342,52 @@ impl From<Bytes> for GroupText { } #[derive(PartialEq, Debug, Clone)] -struct GroupData {} +struct GroupData { + payload: Bytes +} impl From<Bytes> for GroupData { fn from(value: Bytes) -> Self { - todo!() + GroupData { payload: value } } } -#[derive(PartialEq, Debug, Clone)] -struct AnonReq {} +#[derive(PartialEq, Debug, Clone, Difference)] +#[difference(expose)] +struct AnonReq { + destination: u8, + public_key: PublicKey, + mac: u16, + ciphertext: Bytes, + incomplete: bool +} impl From<Bytes> for AnonReq { fn from(value: Bytes) -> Self { - todo!() + let mut bytes = value; + + let mut anon_req = AnonReq { + destination: 0x00, + public_key: PublicKey::default(), + mac: 0x0000, + ciphertext: Bytes::new(), + incomplete: false, + }; + + if bytes.len() == 0 { return anon_req; } + anon_req.destination = bytes.get_u8(); + + if bytes.len() < 32 { return anon_req; } + if let Ok(pub_key) = PublicKey::try_from(bytes.split_to(32)) { + anon_req.public_key = pub_key; + } + + if bytes.len() < 2 { return anon_req; } + anon_req.mac = bytes.get_u16(); + + anon_req.ciphertext = bytes; + anon_req.incomplete = false; + anon_req } } @@ -369,7 +398,9 @@ struct Path { impl From<Bytes> for Path { fn from(value: Bytes) -> Self { - todo!() + Path { + cipher: PeerToPeerCipher::from(value) + } } } @@ -409,11 +440,13 @@ impl From<Bytes> for Trace { } #[derive(PartialEq, Debug, Clone)] -struct MultiPart {} +struct MultiPart { + payload: Bytes +} impl From<Bytes> for MultiPart { fn from(value: Bytes) -> Self { - todo!() + MultiPart { payload: value } } } @@ -454,8 +487,8 @@ impl From<Bytes> for Packet { // The packet isn't long enough to contain the transport if bytes.len() < 4 { return packet; } - let t1 = bytes.get_u16(); - let t2 = bytes.get_u16(); + let t1 = bytes.get_u16_le(); + let t2 = bytes.get_u16_le(); [t1, t2] }, _ => { @@ -638,7 +671,7 @@ mod tests { content: PacketContent::Raw(Raw { bytes: Bytes::copy_from_slice(&[0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19])}), incomplete: false, }; - let rhs_packet = Packet::from_str("3F0102030405060708090A10111213141516171819").unwrap(); + let rhs_packet = Packet::from_str("3F0201040305060708090A10111213141516171819").unwrap(); assert!(lhs_packet == rhs_packet, "{}", print_compare(lhs_packet, rhs_packet)); } @@ -841,7 +874,96 @@ mod tests { cleartext: None, // "Just need some more high repeaters".to_owned() incomplete: false }), - incomplete: false + incomplete: false + }; + + let rhs_packet = Packet::from_str(sample).unwrap(); + assert!(lhs_packet == rhs_packet, "{}", print_compare(lhs_packet, rhs_packet)); + } + + #[test] + fn multipart() { + let sample = "2A0013E8C59624"; + + let lhs_packet = Packet { + route_type: RouteType::Direct, + version: PayloadVersion::VersionOne, + path: vec![], + transport: [0, 0], + raw_content: Bytes::copy_from_slice(&decode("13E8C59624").unwrap()), + content: PacketContent::Multipart(MultiPart { + payload: Bytes::copy_from_slice(&decode("13E8C59624").unwrap()) + }), + incomplete: false + }; + + let rhs_packet = Packet::from_str(sample).unwrap(); + assert!(lhs_packet == rhs_packet, "{}", print_compare(lhs_packet, rhs_packet)); + } + + #[test] + fn group_data() { + let sample = "18079DBB163F3C88707DF4C430C8A06A587CF7E827641C6521A5DE85581C8800793AF4A5497196CB5F24B92A33A9C8AA3BAE4F8C94E8E464849BCBF6333509C3941C47B7ABF85ECFD2FF06DA1A39575D155941F152F63300D2C31B5FAFBDA79637"; + + let lhs_packet = Packet { + route_type: RouteType::TransportFlood, + version: PayloadVersion::VersionOne, + path: vec![0x3C, 0x88, 0x70, 0x7D, 0xF4, 0xC4, 0x30, 0xC8, 0xA0, 0x6A, 0x58, 0x7C, 0xF7, 0xE8, 0x27, 0x64, 0x1C, 0x65, 0x21, 0xA5, 0xDE, 0x85, 0x58, 0x1C, 0x88, 0x00, 0x79, 0x3A, 0xF4, 0xA5, 0x49, 0x71, 0x96, 0xCB, 0x5F, 0x24, 0xB9, 0x2A, 0x33, 0xA9, 0xC8, 0xAA, 0x3B, 0xAE, 0x4F, 0x8C, 0x94, 0xE8, 0xE4, 0x64, 0x84, 0x9B, 0xCB, 0xF6, 0x33, 0x35, 0x09, 0xC3, 0x94, 0x1C, 0x47, 0xB7, 0xAB], + transport: [0x9d07, 0x16bb], + raw_content: Bytes::copy_from_slice(&decode("F85ECFD2FF06DA1A39575D155941F152F63300D2C31B5FAFBDA79637").unwrap()), + content: PacketContent::GroupData(GroupData { + payload: Bytes::copy_from_slice(&decode("F85ECFD2FF06DA1A39575D155941F152F63300D2C31B5FAFBDA79637").unwrap()) + }), + incomplete: false + }; + + let rhs_packet = Packet::from_str(sample).unwrap(); + assert!(lhs_packet == rhs_packet, "{}", print_compare(lhs_packet, rhs_packet)); + } + + #[test] + fn anon_req() { + let sample = "1d001234569df1f9661916901669666fb8025eccb9ddb0499cddad4c164fec219c8b8fd2db15a7138098557cc291928b4358fa7522ddd41d35c99fb78f0def2b3e673d73d2"; + + let lhs_packet = Packet { + route_type: RouteType::Flood, + version: PayloadVersion::VersionOne, + path: vec![], + transport: [0, 0], + raw_content: Bytes::copy_from_slice(&decode("1234569df1f9661916901669666fb8025eccb9ddb0499cddad4c164fec219c8b8fd2db15a7138098557cc291928b4358fa7522ddd41d35c99fb78f0def2b3e673d73d2").unwrap()), + content: PacketContent::AnonReq(AnonReq { + destination: 0x12, + public_key: PublicKey::try_from(Bytes::copy_from_slice(&decode("34569df1f9661916901669666fb8025eccb9ddb0499cddad4c164fec219c8b8f").unwrap())).unwrap(), + mac: 0xd2db, + ciphertext: Bytes::copy_from_slice(&decode("15a7138098557cc291928b4358fa7522ddd41d35c99fb78f0def2b3e673d73d2").unwrap()), + incomplete: false + }), + incomplete: false + }; + + let rhs_packet = Packet::from_str(sample).unwrap(); + assert!(lhs_packet == rhs_packet, "{}", print_compare(lhs_packet, rhs_packet)); + } + + #[test] + fn path() { + let sample = "2107BA03127F7EA9221351768DD2DF32E1D02F5851379F5AFCC667AB273442FAB2943673F26DDBEB9595027474"; + + let lhs_packet = Packet { + route_type: RouteType::Flood, + version: PayloadVersion::VersionOne, + path: vec![0xBA, 0x03, 0x12, 0x7F, 0x7E, 0xA9, 0x22], + transport: [0, 0], + raw_content: Bytes::copy_from_slice(&decode("1351768DD2DF32E1D02F5851379F5AFCC667AB273442FAB2943673F26DDBEB9595027474").unwrap()), + content: PacketContent::Path(Path { + cipher: PeerToPeerCipher { + destination: 0x13, + source: 0x51, + mac: 0x768D, + ciphertext: Bytes::copy_from_slice(&decode("D2DF32E1D02F5851379F5AFCC667AB273442FAB2943673F26DDBEB9595027474").unwrap()) + } + }), + incomplete: false }; let rhs_packet = Packet::from_str(sample).unwrap(); |
