added byte level check
This commit is contained in:
parent
70ec75ff87
commit
de660ad26c
@ -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>;
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user