From 13c9491e49481f9800b297c4077653f1d42efd84 Mon Sep 17 00:00:00 2001 From: "Dr. Maxim Orlovsky" Date: Mon, 21 Nov 2022 15:29:34 +0100 Subject: [PATCH] Implement framer and multiplexer --- radicle-node/src/wire.rs | 4 +- radicle-node/src/wire/transcoder.rs | 132 ++++++++++++++++++++++++++-- 2 files changed, 127 insertions(+), 9 deletions(-) diff --git a/radicle-node/src/wire.rs b/radicle-node/src/wire.rs index 2d65aa29..1204caa1 100644 --- a/radicle-node/src/wire.rs +++ b/radicle-node/src/wire.rs @@ -542,7 +542,7 @@ where deserializer, }) = self.inboxes.get_mut(addr) { - let bytes = transcoder.decrypt(raw_bytes); + let bytes = transcoder.decode(raw_bytes); deserializer.input(&bytes); loop { @@ -584,7 +584,7 @@ impl Iterator for Wire { let Inbox { transcoder, .. } = self.inboxes.get_mut(&addr).expect( "broken handshake implementation: data sent before handshake was complete", ); - let data = transcoder.encrypt(buf); + let data = transcoder.encode(buf); Some(nakamoto::Io::Write(addr, data)) } Some(Io::Event(e)) => Some(nakamoto::Io::Event(e)), diff --git a/radicle-node/src/wire/transcoder.rs b/radicle-node/src/wire/transcoder.rs index db2ff46b..2f25920a 100644 --- a/radicle-node/src/wire/transcoder.rs +++ b/radicle-node/src/wire/transcoder.rs @@ -1,5 +1,9 @@ -use nakamoto_net::Link; +use std::collections::VecDeque; use std::convert::Infallible; +use std::io; +use std::io::Read; + +use nakamoto_net::Link; // TODO: Implement Try trait once stabilized /// Result of a state-machine transition. @@ -50,15 +54,14 @@ impl Handshake for NoHandshake { } } -/// Trait allowing transcoding a stream using some form of stream encryption -/// and/or encoding. +/// Trait allowing transcoding a stream using some form of stream encryption and/or encoding. pub trait Transcode { /// Decodes data received from the remote peer and update the internal state /// of the transcoder, if necessary. - fn decrypt(&mut self, data: &[u8]) -> Vec; + fn decode(&mut self, data: &[u8]) -> Vec; /// Encodes data before sending it to the remote peer. - fn encrypt(&mut self, data: Vec) -> Vec; + fn encode(&mut self, data: Vec) -> Vec; } /// Transcoder which does nothing. @@ -66,11 +69,126 @@ pub trait Transcode { pub struct PlainTranscoder; impl Transcode for PlainTranscoder { - fn decrypt(&mut self, data: &[u8]) -> Vec { + fn decode(&mut self, data: &[u8]) -> Vec { data.to_vec() } - fn encrypt(&mut self, data: Vec) -> Vec { + fn encode(&mut self, data: Vec) -> Vec { data } } + +pub type Frame = Vec; + +#[derive(Copy, Clone, Debug)] +pub struct OversizedData(usize); + +#[derive(Debug, Default)] +pub struct Framer { + input: VecDeque, + inner: T, +} + +impl Framer { + pub fn new(inner: T) -> Self { + Framer { + input: Default::default(), + inner, + } + } + + pub fn input(&mut self, encoded: &[u8]) { + self.input.extend(self.inner.decode(encoded)); + } + + pub fn frame(&mut self, decoded: Vec) -> Result { + let mut data = self.inner.encode(decoded); + let len = data.len(); + let len = u8::try_from(len).map_err(|_| OversizedData(len))?; + let len = len.to_be_bytes(); + let mut buf = Vec::with_capacity(data.len() + 2); + buf.extend(len); + buf.append(&mut data); + Ok(buf) + } +} + +impl Iterator for Framer { + type Item = Frame; + + fn next(&mut self) -> Option { + if self.input.len() < 2 { + return None; + } + let mut len = [0u8; 2]; + self.input + .read_exact(&mut len) + .expect("the length is checked"); + let len = u16::from_be_bytes(len) as usize; + if self.input.len() < 2 + len { + return None; + } + self.input.pop_front(); + self.input.pop_front(); + let reminder = self.input.split_off(len); + let mut data = vec![0u8; len]; + self.input.read_exact(&mut data).expect("checked length"); + self.input = reminder; + Some(data) + } +} + +#[derive(Copy, Clone, Debug)] +pub struct ChannelError; + +#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] +pub struct MuxMsg { + pub channel: u16, + pub data: Vec, +} + +impl TryFrom for MuxMsg { + type Error = ChannelError; + + fn try_from(frame: Frame) -> Result { + if frame.len() < 2 { + return Err(ChannelError); + } + let mut channel = [0u8; 2]; + let mut cursor = io::Cursor::new(frame); + cursor + .read_exact(&mut channel) + .expect("the length is checked"); + let channel = u16::from_be_bytes(channel); + Ok(MuxMsg { + channel, + data: cursor.into_inner(), + }) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn transcode() { + let mut pipeline = Framer::new(PlainTranscoder); + + let data = [ + 0x00, 0x04, 0x00, 0x00, b'a', b'b', 0x00, 0x07, 0x00, 0x01, b'M', b'a', b'x', b'i', + b'm', + ]; + let mut expected_payloads = [(0u16, b"ab".to_vec()), (1, b"Maxim".to_vec())].into_iter(); + + for byte in data { + // Writing data byte by byte, ensuring that the reading is not broken + pipeline.input(&[byte]); + for frame in &mut pipeline { + let msg = MuxMsg::try_from(frame).unwrap(); + let (channel, data) = expected_payloads.next().unwrap(); + assert_eq!(msg, MuxMsg { channel, data }); + } + } + } +}