Skip to content

Commit

Permalink
framing2 module
Browse files Browse the repository at this point in the history
  • Loading branch information
plebhash committed Apr 13, 2024
1 parent e3f0bac commit 5e2ccd5
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 210 deletions.
46 changes: 46 additions & 0 deletions protocols/v2/framing-sv2/src/framing2/either_frame.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use crate::{
framing2::{frame::Frame, noise_frame::NoiseFrame, sv2_frame::Sv2Frame},
Error,
};
use binary_sv2::{GetSize, Serialize};
use core::convert::TryFrom;

pub type HandShakeFrame = NoiseFrame;

#[derive(Debug)]
pub enum EitherFrame<T, B> {
HandShake(HandShakeFrame),
Sv2(Sv2Frame<T, B>),
}

impl<T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> EitherFrame<T, B> {
pub fn encoded_length(&self) -> usize {
match &self {
Self::HandShake(frame) => frame.encoded_length(),
Self::Sv2(frame) => frame.encoded_length(),
}
}
}

impl<T, B> TryFrom<EitherFrame<T, B>> for HandShakeFrame {
type Error = Error;

fn try_from(v: EitherFrame<T, B>) -> Result<Self, Error> {
match v {
EitherFrame::HandShake(frame) => Ok(frame),
EitherFrame::Sv2(_) => Err(Error::ExpectedHandshakeFrame),
}
}
}

impl<T, B> From<HandShakeFrame> for EitherFrame<T, B> {
fn from(v: HandShakeFrame) -> Self {
Self::HandShake(v)
}
}

impl<T, B> From<Sv2Frame<T, B>> for EitherFrame<T, B> {
fn from(v: Sv2Frame<T, B>) -> Self {
Self::Sv2(v)
}
}
40 changes: 40 additions & 0 deletions protocols/v2/framing-sv2/src/framing2/frame.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use crate::Error;

use binary_sv2::{GetSize, Serialize};

pub trait Frame<'a, T: Serialize + GetSize>: Sized {
type Buffer: AsMut<[u8]>;
type Deserialized;

/// Serialize the frame into dst if the frame is already serialized it just swap dst with
/// itself
fn serialize(self, dst: &mut [u8]) -> Result<(), Error>;

//fn deserialize(&'a mut self) -> Result<Self::Deserialized, serde_sv2::Error>;

fn payload(&'a mut self) -> &'a mut [u8];

/// If is an Sv2 frame return the Some(header) if it is a noise frame return None
fn get_header(&self) -> Option<crate::header::Header>;

/// Try to build an Frame frame from raw bytes.
/// It return the frame or the number of the bytes needed to complete the frame
/// The resulting frame is just a header plus a payload with the right number of bytes nothing
/// is said about the correctness of the payload
fn from_bytes(bytes: Self::Buffer) -> Result<Self, isize>;

fn from_bytes_unchecked(bytes: Self::Buffer) -> Self;

fn size_hint(bytes: &[u8]) -> isize;

fn encoded_length(&self) -> usize;

/// Try to build an Frame frame from a serializable payload.
/// It return a Frame if the size of the payload fit in the frame, if not it return None
fn from_message(
message: T,
message_type: u8,
extension_type: u16,
channel_msg: bool,
) -> Option<Self>;
}
4 changes: 4 additions & 0 deletions protocols/v2/framing-sv2/src/framing2/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub mod either_frame;
pub mod frame;
pub mod noise_frame;
pub mod sv2_frame;
104 changes: 104 additions & 0 deletions protocols/v2/framing-sv2/src/framing2/noise_frame.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use crate::{framing2::frame::Frame, header::NoiseHeader, Error};

use alloc::vec::Vec;

const NOISE_MAX_LEN: usize = const_sv2::NOISE_FRAME_MAX_SIZE;

#[cfg(not(feature = "with_buffer_pool"))]
type Slice = Vec<u8>;
#[cfg(feature = "with_buffer_pool")]
type Slice = buffer_sv2::Slice;

#[derive(Debug)]
pub struct NoiseFrame {
payload: Slice,
}

impl NoiseFrame {
pub fn get_payload_when_handshaking(&self) -> Vec<u8> {
self.payload[0..].to_vec()
}
}

impl<'a> Frame<'a, Slice> for NoiseFrame {
type Buffer = Slice;
type Deserialized = &'a mut [u8];

/// Serialize the frame into dst if the frame is already serialized it just swap dst with
/// itself
#[inline]
fn serialize(mut self, dst: &mut [u8]) -> Result<(), Error> {
dst.swap_with_slice(self.payload.as_mut());
Ok(())
}

#[inline]
fn payload(&'a mut self) -> &'a mut [u8] {
&mut self.payload[NoiseHeader::HEADER_SIZE..]
}

/// If is an Sv2 frame return the Some(header) if it is a noise frame return None
fn get_header(&self) -> Option<crate::header::Header> {
None
}

// For a NoiseFrame from_bytes is the same of from_bytes_unchecked
fn from_bytes(bytes: Self::Buffer) -> Result<Self, isize> {
Ok(Self::from_bytes_unchecked(bytes))
}

#[inline]
fn from_bytes_unchecked(bytes: Self::Buffer) -> Self {
Self { payload: bytes }
}

#[inline]
fn size_hint(bytes: &[u8]) -> isize {
if bytes.len() < NoiseHeader::HEADER_SIZE {
return (NoiseHeader::HEADER_SIZE - bytes.len()) as isize;
};

let len_b = &bytes[NoiseHeader::LEN_OFFSET..NoiseHeader::HEADER_SIZE];
let expected_len = u16::from_le_bytes([len_b[0], len_b[1]]) as usize;

if bytes.len() - NoiseHeader::HEADER_SIZE == expected_len {
0
} else {
expected_len as isize - (bytes.len() - NoiseHeader::HEADER_SIZE) as isize
}
}

#[inline]
fn encoded_length(&self) -> usize {
self.payload.len()
}

/// Try to build a `Frame` frame from a serializable payload.
/// It returns a Frame if the size of the payload fits in the frame, if not it returns None
/// Inneficient should be used only to build `HandShakeFrames`
/// TODO check if is used only to build `HandShakeFrames`
#[allow(clippy::useless_conversion)]
fn from_message(
message: Slice,
_message_type: u8,
_extension_type: u16,
_channel_msg: bool,
) -> Option<Self> {
if message.len() <= NOISE_MAX_LEN {
Some(Self {
payload: message.into(),
})
} else {
None
}
}
}

#[allow(clippy::useless_conversion)]
pub fn handshake_message_to_frame<T: AsRef<[u8]>>(message: T) -> NoiseFrame {
let mut payload = Vec::new();
payload.extend_from_slice(message.as_ref());
NoiseFrame {
payload: payload.into(),
}
}
Loading

0 comments on commit 5e2ccd5

Please sign in to comment.