added byte level check

This commit is contained in:
Robin Müller 2022-06-18 19:51:54 +02:00
parent 70ec75ff87
commit de660ad26c
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
3 changed files with 78 additions and 53 deletions

View File

@ -31,8 +31,6 @@ pub trait PusPacket: CcsdsPacket {
fn service(&self) -> u8; fn service(&self) -> u8;
fn subservice(&self) -> u8; fn subservice(&self) -> u8;
fn source_id(&self) -> u16;
fn ack_flags(&self) -> u8;
fn user_data(&self) -> Option<&[u8]>; fn user_data(&self) -> Option<&[u8]>;
fn crc16(&self) -> Option<u16>; fn crc16(&self) -> Option<u16>;

View File

@ -268,7 +268,7 @@ pub mod srd {
} }
} }
impl SpHeader { impl SpHeader {
pub fn new(apid: u16, ptype: PacketType, ssc: u16) -> Option<Self> { pub fn new(apid: u16, ptype: PacketType, ssc: u16, data_len: u16) -> Option<Self> {
if ssc > num::pow(2, 14) - 1 || apid > num::pow(2, 11) - 1 { if ssc > num::pow(2, 14) - 1 || apid > num::pow(2, 11) - 1 {
return None; return None;
} }
@ -276,15 +276,16 @@ pub mod srd {
header.packet_id.apid = apid; header.packet_id.apid = apid;
header.packet_id.ptype = ptype; header.packet_id.ptype = ptype;
header.psc.ssc = ssc; header.psc.ssc = ssc;
header.data_len = data_len;
Some(header) Some(header)
} }
pub fn tm(apid: u16, ssc: u16) -> Option<Self> { pub fn tm(apid: u16, ssc: u16, data_len: u16) -> Option<Self> {
Self::new(apid, PacketType::Tm, ssc) Self::new(apid, PacketType::Tm, ssc, data_len)
} }
pub fn tc(apid: u16, ssc: u16) -> Option<Self> { pub fn tc(apid: u16, ssc: u16, data_len: u16) -> Option<Self> {
Self::new(apid, PacketType::Tc, ssc) Self::new(apid, PacketType::Tc, ssc, data_len)
} }
} }
@ -474,7 +475,7 @@ mod tests {
#[test] #[test]
fn test_serde_sph() { fn test_serde_sph() {
let sp_header = SpHeader::tc(0x42, 12).expect("Error creating SP header"); let sp_header = SpHeader::tc(0x42, 12, 0).expect("Error creating SP header");
assert_eq!(sp_header.ccsds_version(), 0b000); assert_eq!(sp_header.ccsds_version(), 0b000);
assert!(sp_header.is_tc()); assert!(sp_header.is_tc());
assert!(sp_header.sec_header_flag()); assert!(sp_header.sec_header_flag());
@ -496,8 +497,7 @@ mod tests {
assert_eq!(sp_header.ccsds_version(), 0b000); assert_eq!(sp_header.ccsds_version(), 0b000);
assert_eq!(sp_header.data_len, 0); assert_eq!(sp_header.data_len, 0);
let mut sp_header = SpHeader::tm(0x7, 22).expect("Error creating SP header"); let sp_header = SpHeader::tm(0x7, 22, 36).expect("Error creating SP header");
sp_header.data_len = 36;
assert_eq!(sp_header.ccsds_version(), 0b000); assert_eq!(sp_header.ccsds_version(), 0b000);
assert!(sp_header.is_tm()); assert!(sp_header.is_tm());
assert!(sp_header.sec_header_flag()); assert!(sp_header.sec_header_flag());
@ -531,7 +531,8 @@ mod tests {
fn test_zc_sph() { fn test_zc_sph() {
use zerocopy::AsBytes; use zerocopy::AsBytes;
let sp_header = SpHeader::tc(0x7FF, num::pow(2, 14) - 1).expect("Error creating SP header"); let sp_header =
SpHeader::tc(0x7FF, num::pow(2, 14) - 1, 0).expect("Error creating SP header");
assert_eq!(sp_header.ptype(), PacketType::Tc); assert_eq!(sp_header.ptype(), PacketType::Tc);
assert_eq!(sp_header.apid(), 0x7FF); assert_eq!(sp_header.apid(), 0x7FF);
assert_eq!(sp_header.data_len(), 0); assert_eq!(sp_header.data_len(), 0);
@ -572,7 +573,6 @@ mod tests {
let sp_header = zc::SpHeader::from_bytes(slice); let sp_header = zc::SpHeader::from_bytes(slice);
assert!(sp_header.is_some()); assert!(sp_header.is_some());
let sp_header = sp_header.unwrap(); let sp_header = sp_header.unwrap();
println!("Header: {:?}", sp_header);
assert_eq!(sp_header.ccsds_version(), 0b000); assert_eq!(sp_header.ccsds_version(), 0b000);
assert_eq!(sp_header.packet_id_raw(), 0x1FFF); assert_eq!(sp_header.packet_id_raw(), 0x1FFF);
assert_eq!(sp_header.apid(), 0x7FF); assert_eq!(sp_header.apid(), 0x7FF);

View File

@ -1,4 +1,4 @@
use crate::ecss::{PusPacket, PusVersion}; use crate::ecss::PusVersion;
use crate::CCSDS_HEADER_LEN; use crate::CCSDS_HEADER_LEN;
use std::mem::size_of; use std::mem::size_of;
@ -30,24 +30,6 @@ pub trait PusTcSecondaryHeader {
fn source_id(&self) -> u16; fn source_id(&self) -> u16;
} }
impl<T: PusPacket> PusTcSecondaryHeader for T {
fn ack_flags(&self) -> u8 {
self.ack_flags()
}
fn service(&self) -> u8 {
self.service()
}
fn subservice(&self) -> u8 {
self.subservice()
}
fn source_id(&self) -> u16 {
self.source_id()
}
}
pub mod zc { pub mod zc {
use crate::ecss::{PusError, PusVersion}; use crate::ecss::{PusError, PusVersion};
use crate::tc::{srd, PusTcSecondaryHeader}; use crate::tc::{srd, PusTcSecondaryHeader};
@ -338,21 +320,20 @@ pub mod srd {
PacketError::FromBytesZeroCopyError, PacketError::FromBytesZeroCopyError,
))?; ))?;
current_idx += PUC_TC_SECONDARY_HEADER_LEN; current_idx += PUC_TC_SECONDARY_HEADER_LEN;
let app_data;
if current_idx > total_len - 2 {
return Err(PusError::RawDataTooShort(raw_data_len));
} else if current_idx == total_len - 2 {
app_data = None
} else {
app_data = Some(&slice_ref[current_idx..total_len - 2]);
}
let mut pus_tc = PusTc { let mut pus_tc = PusTc {
sph: SpHeader::from(sph), sph: SpHeader::from(sph),
data_field_header: PusTcDataFieldHeader::try_from(sec_header).unwrap(), data_field_header: PusTcDataFieldHeader::try_from(sec_header).unwrap(),
raw_data: Some(slice_ref), raw_data: Some(slice_ref),
app_data, app_data: match current_idx {
_ if current_idx == total_len - 2 => None,
_ if current_idx > total_len - 2 => {
return Err(PusError::RawDataTooShort(raw_data_len))
}
_ => Some(&slice_ref[current_idx..total_len - 2]),
},
crc16: None, crc16: None,
}; };
pus_tc.crc_from_raw_data()?;
pus_tc.verify()?; pus_tc.verify()?;
Ok((pus_tc, total_len)) Ok((pus_tc, total_len))
} }
@ -387,8 +368,6 @@ pub mod srd {
delegate!(to self.data_field_header { delegate!(to self.data_field_header {
fn service(&self) -> u8; fn service(&self) -> u8;
fn subservice(&self) -> u8; fn subservice(&self) -> u8;
fn source_id(&self) -> u16;
fn ack_flags(&self) -> u8;
}); });
fn user_data(&self) -> Option<&[u8]> { fn user_data(&self) -> Option<&[u8]> {
@ -399,6 +378,16 @@ pub mod srd {
self.crc16 self.crc16
} }
} }
//noinspection RsTraitImplementation
impl PusTcSecondaryHeader for PusTc<'_> {
delegate!(to self.data_field_header {
fn service(&self) -> u8;
fn subservice(&self) -> u8;
fn source_id(&self) -> u16;
fn ack_flags(&self) -> u8;
});
}
} }
#[cfg(test)] #[cfg(test)]
@ -406,42 +395,80 @@ mod tests {
use crate::ecss::PusPacket; use crate::ecss::PusPacket;
use crate::srd::SpHeader; use crate::srd::SpHeader;
use crate::tc::srd::PusTc; use crate::tc::srd::PusTc;
use crate::tc::PusTcSecondaryHeader;
use crate::tc::ACK_ALL; use crate::tc::ACK_ALL;
use crate::CcsdsPacket; use crate::{CcsdsPacket, PacketType};
use postcard::to_stdvec; use postcard::to_stdvec;
#[test] #[test]
fn test_tc() { fn test_tc() {
let mut sph = SpHeader::tc(0x01, 0).unwrap(); let mut sph = SpHeader::tc(0x01, 0, 0).unwrap();
let mut pus_tc = PusTc::new(&mut sph, 17, 1, None); let mut pus_tc = PusTc::new(&mut sph, 17, 1, None);
verify_test_tc(&pus_tc);
let _out = to_stdvec(&pus_tc).unwrap(); let _out = to_stdvec(&pus_tc).unwrap();
assert_eq!(pus_tc.crc16(), None);
let mut test_buf: [u8; 32] = [0; 32]; let mut test_buf: [u8; 32] = [0; 32];
pus_tc.update_packet_fields(); pus_tc.update_packet_fields();
verify_test_tc(&pus_tc);
assert_eq!(pus_tc.len_packed(), 13); assert_eq!(pus_tc.len_packed(), 13);
let size = pus_tc let size = pus_tc
.copy_to_buf(test_buf.as_mut_slice()) .copy_to_buf(test_buf.as_mut_slice())
.expect("Error writing TC to buffer"); .expect("Error writing TC to buffer");
let (tc_from_raw, sz) = PusTc::new_from_raw_slice(&test_buf) assert_eq!(size, 13);
let (tc_from_raw, mut size) = PusTc::new_from_raw_slice(&test_buf)
.expect("Creating PUS TC struct from raw buffer failed"); .expect("Creating PUS TC struct from raw buffer failed");
assert_eq!(sz, 13); assert_eq!(size, 13);
verify_test_tc(&tc_from_raw); verify_test_tc(&tc_from_raw);
println!("Test buffer: {:02x?} with {size} written bytes", test_buf); verify_test_tc_raw(PacketType::Tm, &test_buf);
let mut test_vec = Vec::new(); let mut test_vec = Vec::new();
let size = pus_tc size = pus_tc
.append_to_vec(&mut test_vec) .append_to_vec(&mut test_vec)
.expect("Error writing TC to vector"); .expect("Error writing TC to vector");
println!("Test Vector: {:02x?} with {size} written bytes", test_vec); assert_eq!(size, 13);
assert_eq!(&test_buf[0..pus_tc.len_packed()], test_vec.as_slice());
verify_test_tc_raw(PacketType::Tm, &test_vec.as_slice());
} }
fn verify_test_tc(tc: &PusTc) { fn verify_test_tc(tc: &PusTc) {
assert_eq!(tc.service(), 17); assert_eq!(PusPacket::service(tc), 17);
assert_eq!(tc.subservice(), 1); assert_eq!(PusPacket::subservice(tc), 1);
assert_eq!(tc.user_data(), None); assert_eq!(tc.user_data(), None);
assert_eq!(tc.source_id(), 0); assert_eq!(tc.source_id(), 0);
assert_eq!(tc.apid(), 0x01); assert_eq!(tc.apid(), 0x01);
assert_eq!(tc.ack_flags(), ACK_ALL); assert_eq!(tc.ack_flags(), ACK_ALL);
assert_eq!(tc.crc16(), None); assert_eq!(tc.sph, SpHeader::tc(0x01, 0, 6).unwrap());
}
fn verify_test_tc_raw(ptype: PacketType, slice: &impl AsRef<[u8]>) {
// Reference comparison implementation:
// https://github.com/robamu-org/py-spacepackets/blob/main/examples/example_pus.py
let slice = slice.as_ref();
// 0x1801 is the generic
if ptype == PacketType::Tm {
assert_eq!(slice[0], 0x18);
} else {
assert_eq!(slice[0], 0x08);
}
// APID is 0x01
assert_eq!(slice[1], 0x01);
// Unsegmented packets
assert_eq!(slice[2], 0xc0);
// Sequence count 0
assert_eq!(slice[3], 0x00);
assert_eq!(slice[4], 0x00);
// Space data length of 6 equals total packet length of 13
assert_eq!(slice[5], 0x06);
// PUS Version C 0b0010 and ACK flags 0b1111
assert_eq!(slice[6], 0x2f);
// Service 17
assert_eq!(slice[7], 0x11);
// Subservice 1
assert_eq!(slice[8], 0x01);
// Source ID 0
assert_eq!(slice[9], 0x00);
assert_eq!(slice[10], 0x00);
// CRC first byte assuming big endian format is 0x16 and 0x1d
assert_eq!(slice[11], 0x16);
assert_eq!(slice[12], 0x1d);
} }
} }