CFDP initial packet support #14
@ -3,6 +3,7 @@ use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub mod pdu;
|
||||
pub mod tlv;
|
||||
|
||||
pub const CFDP_VERSION_2_NAME: &str = "CCSDS 727.0-B-5";
|
||||
pub const CFDP_VERSION_2: u8 = 0b001;
|
||||
|
15
src/cfdp/pdu/metadata.rs
Normal file
15
src/cfdp/pdu/metadata.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use crate::cfdp::pdu::{FileDirectiveType, PduHeader};
|
||||
use crate::cfdp::ChecksumType;
|
||||
|
||||
pub struct MetadataParams {
|
||||
closure_requested: bool,
|
||||
checksum_type: ChecksumType,
|
||||
file_size: u64,
|
||||
//src_file_name:
|
||||
}
|
||||
|
||||
pub struct MetadataPdu {
|
||||
pdu_header: PduHeader,
|
||||
file_directive: FileDirectiveType,
|
||||
metadata_params: MetadataParams,
|
||||
}
|
@ -5,6 +5,21 @@ use core::fmt::{Display, Formatter};
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
|
||||
pub mod metadata;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[repr(u8)]
|
||||
pub enum FileDirectiveType {
|
||||
EofPdu = 0x04,
|
||||
FinishedPdu = 0x05,
|
||||
AckPdu = 0x06,
|
||||
MetadataPdu = 0x07,
|
||||
NakPdu = 0x08,
|
||||
PromptPdu = 0x09,
|
||||
KeepAlivePdu = 0x0c,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub enum PduError {
|
||||
@ -148,7 +163,7 @@ impl CommonPduConfig {
|
||||
}
|
||||
}
|
||||
|
||||
const FIXED_HEADER_LEN: usize = 4;
|
||||
pub const FIXED_HEADER_LEN: usize = 4;
|
||||
|
||||
/// Abstraction for the PDU header common to all CFDP PDUs
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
|
86
src/cfdp/tlv.rs
Normal file
86
src/cfdp/tlv.rs
Normal file
@ -0,0 +1,86 @@
|
||||
use crate::{ByteConversionError, SizeMissmatch};
|
||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub const MIN_TLV_LEN: usize = 2;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[repr(u8)]
|
||||
pub enum TlvType {
|
||||
FilestoreRequest = 0x00,
|
||||
FilestoreResponse = 0x01,
|
||||
MsgToUser = 0x02,
|
||||
FaultHandler = 0x04,
|
||||
FlowLabel = 0x05,
|
||||
EntityId = 0x06,
|
||||
}
|
||||
|
||||
pub struct Tlv<'a> {
|
||||
tlv_type: TlvType,
|
||||
data: &'a [u8],
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub enum TlvError {
|
||||
DataTooLarge(usize),
|
||||
ByteConversionError(ByteConversionError),
|
||||
UnknownTlvType(u8),
|
||||
}
|
||||
|
||||
impl From<ByteConversionError> for TlvError {
|
||||
fn from(value: ByteConversionError) -> Self {
|
||||
Self::ByteConversionError(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Tlv<'a> {
|
||||
pub fn new(tlv_type: TlvType, data: &[u8]) -> Result<Tlv, TlvError> {
|
||||
if data.len() > u8::MAX as usize {
|
||||
return Err(TlvError::DataTooLarge(data.len()));
|
||||
}
|
||||
Ok(Tlv { tlv_type, data })
|
||||
}
|
||||
|
||||
pub fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||
if buf.len() < self.data.len() + MIN_TLV_LEN {
|
||||
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
|
||||
found: buf.len(),
|
||||
expected: self.data.len() + MIN_TLV_LEN,
|
||||
}));
|
||||
}
|
||||
buf[0] = self.tlv_type as u8;
|
||||
// Length check in constructor ensures the length always has a valid value.
|
||||
buf[1] = self.data.len() as u8;
|
||||
buf[MIN_TLV_LEN..self.data.len() + MIN_TLV_LEN].copy_from_slice(self.data);
|
||||
Ok(MIN_TLV_LEN + self.data.len())
|
||||
}
|
||||
|
||||
pub fn from_be_bytes(buf: &'a [u8]) -> Result<Tlv<'a>, TlvError> {
|
||||
if buf.len() < MIN_TLV_LEN {
|
||||
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch {
|
||||
found: buf.len(),
|
||||
expected: MIN_TLV_LEN,
|
||||
})
|
||||
.into());
|
||||
}
|
||||
let tlv_type_res = TlvType::try_from(buf[0]);
|
||||
if tlv_type_res.is_err() {
|
||||
return Err(TlvError::UnknownTlvType(buf[1]));
|
||||
}
|
||||
let value_len = buf[1] as usize;
|
||||
if buf.len() < value_len {
|
||||
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch {
|
||||
found: buf.len(),
|
||||
expected: MIN_TLV_LEN + value_len,
|
||||
})
|
||||
.into());
|
||||
}
|
||||
Ok(Self {
|
||||
tlv_type: tlv_type_res.unwrap(),
|
||||
data: &buf[MIN_TLV_LEN..MIN_TLV_LEN + value_len],
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user