Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Framing crate refactor: cleanup framing.rs #982

Merged
merged 4 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions protocols/v2/codec-sv2/src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ pub use buffer_sv2::AeadBuffer;
pub use const_sv2::{SV2_FRAME_CHUNK_SIZE, SV2_FRAME_HEADER_SIZE};
use core::marker::PhantomData;
#[cfg(feature = "noise_sv2")]
use framing_sv2::framing2::HandShakeFrame;
use framing_sv2::framing::HandShakeFrame;
#[cfg(feature = "noise_sv2")]
use framing_sv2::header::{NOISE_HEADER_ENCRYPTED_SIZE, NOISE_HEADER_SIZE};
use framing_sv2::{
framing2::{EitherFrame, Sv2Frame},
framing::{Frame, Sv2Frame},
header::Header,
};
#[cfg(feature = "noise_sv2")]
Expand All @@ -36,7 +36,7 @@ use crate::State;

#[cfg(feature = "noise_sv2")]
pub type StandardNoiseDecoder<T> = WithNoise<Buffer, T>;
pub type StandardEitherFrame<T> = EitherFrame<T, <Buffer as IsBuffer>::Slice>;
pub type StandardEitherFrame<T> = Frame<T, <Buffer as IsBuffer>::Slice>;
pub type StandardSv2Frame<T> = Sv2Frame<T, <Buffer as IsBuffer>::Slice>;
pub type StandardDecoder<T> = WithoutNoise<Buffer, T>;

Expand All @@ -51,7 +51,7 @@ pub struct WithNoise<B: IsBuffer, T: Serialize + binary_sv2::GetSize> {
#[cfg(feature = "noise_sv2")]
impl<'a, T: Serialize + GetSize + Deserialize<'a>, B: IsBuffer + AeadBuffer> WithNoise<B, T> {
#[inline]
pub fn next_frame(&mut self, state: &mut State) -> Result<EitherFrame<T, B::Slice>> {
pub fn next_frame(&mut self, state: &mut State) -> Result<Frame<T, B::Slice>> {
match state {
State::HandShake(_) => unreachable!(),
State::NotInitialized(msg_len) => {
Expand Down Expand Up @@ -97,10 +97,7 @@ impl<'a, T: Serialize + GetSize + Deserialize<'a>, B: IsBuffer + AeadBuffer> Wit
}

#[inline]
fn decode_noise_frame(
&mut self,
noise_codec: &mut NoiseCodec,
) -> Result<EitherFrame<T, B::Slice>> {
fn decode_noise_frame(&mut self, noise_codec: &mut NoiseCodec) -> Result<Frame<T, B::Slice>> {
match (
IsBuffer::len(&self.noise_buffer),
IsBuffer::len(&self.sv2_buffer),
Expand Down Expand Up @@ -148,7 +145,7 @@ impl<'a, T: Serialize + GetSize + Deserialize<'a>, B: IsBuffer + AeadBuffer> Wit
}
}

fn while_handshaking(&mut self) -> EitherFrame<T, B::Slice> {
fn while_handshaking(&mut self) -> Frame<T, B::Slice> {
let src = self.noise_buffer.get_data_owned().as_mut().to_vec();

// below is inffalible as noise frame length has been already checked
Expand Down
6 changes: 3 additions & 3 deletions protocols/v2/codec-sv2/src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ pub use const_sv2::{AEAD_MAC_LEN, SV2_FRAME_CHUNK_SIZE, SV2_FRAME_HEADER_SIZE};
#[cfg(feature = "noise_sv2")]
use core::convert::TryInto;
use core::marker::PhantomData;
use framing_sv2::framing2::Sv2Frame;
use framing_sv2::framing::Sv2Frame;
#[cfg(feature = "noise_sv2")]
use framing_sv2::framing2::{EitherFrame, HandShakeFrame};
use framing_sv2::framing::{Frame, HandShakeFrame};
#[allow(unused_imports)]
pub use framing_sv2::header::NOISE_HEADER_ENCRYPTED_SIZE;

Expand Down Expand Up @@ -43,7 +43,7 @@ pub struct NoiseEncoder<T: Serialize + binary_sv2::GetSize> {
}

#[cfg(feature = "noise_sv2")]
type Item<T> = EitherFrame<T, Slice>;
type Item<T> = Frame<T, Slice>;

#[cfg(feature = "noise_sv2")]
impl<T: Serialize + GetSize> NoiseEncoder<T> {
Expand Down
6 changes: 3 additions & 3 deletions protocols/v2/codec-sv2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ pub use encoder::Encoder;
pub use encoder::NoiseEncoder;

#[cfg(feature = "noise_sv2")]
pub use framing_sv2::framing2::HandShakeFrame;
pub use framing_sv2::framing2::Sv2Frame;
pub use framing_sv2::framing::HandShakeFrame;
pub use framing_sv2::framing::Sv2Frame;

#[cfg(feature = "noise_sv2")]
pub use noise_sv2::{self, Initiator, NoiseCodec, Responder};

pub use buffer_sv2;

pub use framing_sv2::{self, framing2::handshake_message_to_frame as h2f};
pub use framing_sv2::{self, framing::handshake_message_to_frame as h2f};

#[cfg(feature = "noise_sv2")]
#[derive(Debug)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,43 @@
#![allow(dead_code)]
use crate::{
header::{Header, NOISE_HEADER_LEN_OFFSET, NOISE_HEADER_SIZE},
Error,
};
use crate::{header::Header, Error};
use alloc::vec::Vec;
use binary_sv2::{to_writer, GetSize, Serialize};
use core::convert::TryFrom;

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;

impl<A, B> Sv2Frame<A, B> {
/// Maps a `Sv2Frame<A, B>` to `Sv2Frame<C, B>` by applying `fun`,
/// which is assumed to be a closure that converts `A` to `C`
pub fn map<C>(self, fun: fn(A) -> C) -> Sv2Frame<C, B> {
let serialized = self.serialized;
let header = self.header;
let payload = self.payload.map(fun);
Sv2Frame {
header,
payload,
serialized,
/// A wrapper to be used in a context we need a generic reference to a frame
/// but it doesn't matter which kind of frame it is (`Sv2Frame` or `HandShakeFrame`)
#[derive(Debug)]
pub enum Frame<T, B> {
HandShake(HandShakeFrame),
Sv2(Sv2Frame<T, B>),
}

impl<T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Frame<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> From<HandShakeFrame> for Frame<T, B> {
fn from(v: HandShakeFrame) -> Self {
Self::HandShake(v)
}
}

impl<T, B> From<Sv2Frame<T, B>> for Frame<T, B> {
fn from(v: Sv2Frame<T, B>) -> Self {
Self::Sv2(v)
}
}

/// Abstraction for a SV2 Frame.
#[derive(Debug, Clone)]
pub struct Sv2Frame<T, B> {
Expand All @@ -39,21 +47,6 @@ pub struct Sv2Frame<T, B> {
serialized: Option<B>,
}

/// Abstraction for a Noise Handshake Frame
/// Contains only a `Slice` payload with a fixed length
/// Only used during Noise Handshake process
#[derive(Debug)]
pub struct HandShakeFrame {
payload: Slice,
}

impl HandShakeFrame {
/// Returns payload of `HandShakeFrame` as a `Vec<u8>`
pub fn get_payload_when_handshaking(&self) -> Vec<u8> {
self.payload[0..].to_vec()
}
}

impl<T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Sv2Frame<T, B> {
/// Write the serialized `Sv2Frame` into `dst`.
/// This operation when called on an already serialized frame is very cheap.
Expand Down Expand Up @@ -182,23 +175,44 @@ impl<T: Serialize + GetSize, B: AsMut<[u8]> + AsRef<[u8]>> Sv2Frame<T, B> {
}
}

impl HandShakeFrame {
/// Put the Noise Frame payload into `dst`
#[inline]
fn serialize(mut self, dst: &mut [u8]) -> Result<(), Error> {
dst.swap_with_slice(self.payload.as_mut());
Ok(())
impl<A, B> Sv2Frame<A, B> {
/// Maps a `Sv2Frame<A, B>` to `Sv2Frame<C, B>` by applying `fun`,
/// which is assumed to be a closure that converts `A` to `C`
pub fn map<C>(self, fun: fn(A) -> C) -> Sv2Frame<C, B> {
let serialized = self.serialized;
let header = self.header;
let payload = self.payload.map(fun);
Sv2Frame {
header,
payload,
serialized,
}
}
}

/// Get the Noise Frame payload
#[inline]
fn payload(&mut self) -> &mut [u8] {
&mut self.payload[NOISE_HEADER_SIZE..]
impl<T, B> TryFrom<Frame<T, B>> for Sv2Frame<T, B> {
type Error = Error;

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

/// `HandShakeFrame` always returns `None`.
fn get_header(&self) -> Option<crate::header::Header> {
None
/// Abstraction for a Noise Handshake Frame
/// Contains only a `Slice` payload with a fixed length
/// Only used during Noise Handshake process
#[derive(Debug)]
pub struct HandShakeFrame {
payload: Slice,
}

impl HandShakeFrame {
/// Returns payload of `HandShakeFrame` as a `Vec<u8>`
pub fn get_payload_when_handshaking(&self) -> Vec<u8> {
self.payload[0..].to_vec()
}

/// Builds a `HandShakeFrame` from raw bytes. Nothing is assumed or checked about the correctness of the payload.
Expand All @@ -211,52 +225,20 @@ impl HandShakeFrame {
Self { payload: bytes }
}

/// After parsing the expected `HandShakeFrame` size from `bytes`, this function helps to determine if this value
/// correctly representing the size of the frame.
/// - Returns `0` if the byte slice is of the expected size according to the header.
/// - Returns a negative value if the byte slice is smaller than a Noise Frame header; this value
/// represents how many bytes are missing.
/// - Returns a positive value if the byte slice is longer than expected; this value
/// indicates the surplus of bytes beyond the expected size.
#[inline]
fn size_hint(bytes: &[u8]) -> isize {
if bytes.len() < NOISE_HEADER_SIZE {
return (NOISE_HEADER_SIZE - bytes.len()) as isize;
};

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

if bytes.len() - NOISE_HEADER_SIZE == expected_len {
0
} else {
expected_len as isize - (bytes.len() - NOISE_HEADER_SIZE) as isize
}
}

/// Returns the size of the `HandShakeFrame` payload.
#[inline]
fn encoded_length(&self) -> usize {
self.payload.len()
}
}

/// Tries to build a `HandShakeFrame` frame from a byte slice.
/// Returns a `HandShakeFrame` if the size of the payload fits in the frame, `None` otherwise.
/// This is quite inefficient, and 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
impl<T, B> TryFrom<Frame<T, B>> for HandShakeFrame {
type Error = Error;

fn try_from(v: Frame<T, B>) -> Result<Self, Error> {
match v {
Frame::HandShake(frame) => Ok(frame),
Frame::Sv2(_) => Err(Error::ExpectedHandshakeFrame),
}
}
}
Expand Down Expand Up @@ -285,57 +267,6 @@ fn update_extension_type(extension_type: u16, channel_msg: bool) -> u16 {
}
}

/// A wrapper to be used in a context we need a generic reference to a frame
/// but it doesn't matter which kind of frame it is (`Sv2Frame` or `HandShakeFrame`)
#[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> TryFrom<EitherFrame<T, B>> for Sv2Frame<T, B> {
type Error = Error;

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

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)
}
}

#[cfg(test)]
use binary_sv2::binary_codec_sv2;

Expand Down
2 changes: 1 addition & 1 deletion protocols/v2/framing-sv2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
extern crate alloc;

/// SV2 framing types
pub mod framing2;
pub mod framing;

/// SV2 framing errors
pub mod error;
Expand Down
2 changes: 1 addition & 1 deletion protocols/v2/roles-logic-sv2/src/parsers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use binary_sv2::GetSize;

use binary_sv2::{from_bytes, Deserialize};

use framing_sv2::framing2::Sv2Frame;
use framing_sv2::framing::Sv2Frame;

use const_sv2::{
CHANNEL_BIT_ALLOCATE_MINING_JOB_TOKEN, CHANNEL_BIT_ALLOCATE_MINING_JOB_TOKEN_SUCCESS,
Expand Down
Loading