phew
Some checks failed
Rust/sat-rs/pipeline/pr-main There was a failure building this commit

This commit is contained in:
Robin Müller 2023-08-17 22:11:27 +02:00
parent 143b0869a4
commit afd9395cee
Signed by: muellerr
GPG Key ID: A649FB78196E3849
3 changed files with 153 additions and 27 deletions

View File

@ -71,7 +71,7 @@ version = "0.7.0-beta.0"
# path = "../../spacepackets" # path = "../../spacepackets"
git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git" git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git"
# rev = "" # rev = ""
branch = "update-lv-tlv" branch = "pdu-additions"
default-features = false default-features = false
[dev-dependencies] [dev-dependencies]

View File

@ -7,7 +7,7 @@ use std::{
use super::{ use super::{
user::{CfdpUser, MetadataReceivedParams}, user::{CfdpUser, MetadataReceivedParams},
State, TransactionId, TransactionStep, CRC_32, PacketInfo, PacketTarget, State, TransactionId, TransactionStep, CRC_32,
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
use spacepackets::{ use spacepackets::{
@ -20,7 +20,7 @@ use spacepackets::{
CommonPduConfig, FileDirectiveType, PduError, PduHeader, CommonPduConfig, FileDirectiveType, PduError, PduHeader,
}, },
tlv::{msg_to_user::MsgToUserTlv, EntityIdTlv, TlvType}, tlv::{msg_to_user::MsgToUserTlv, EntityIdTlv, TlvType},
ConditionCode, PduType, ConditionCode, PduType, TransmissionMode,
}, },
util::UnsignedByteField, util::UnsignedByteField,
}; };
@ -142,28 +142,29 @@ impl DestinationHandler {
match self.state { match self.state {
State::Idle => todo!(), State::Idle => todo!(),
State::BusyClass1Nacked => self.fsm_nacked(cfdp_user), State::BusyClass1Nacked => self.fsm_nacked(cfdp_user),
State::BusyClass2Acked => todo!(), State::BusyClass2Acked => todo!("acknowledged mode not implemented yet"),
} }
} }
pub fn insert_packet(_raw_packet: &[u8]) -> Result<(), DestError> { pub fn insert_packet(&mut self, packet_info: &PacketInfo) -> Result<(), DestError> {
todo!(); if packet_info.target() != PacketTarget::DestEntity {
//Ok(()) // Unwrap is okay here, a PacketInfo for a file data PDU should always have the
} // destination as the target.
pub fn insert_packet_with_known_type( return Err(DestError::CantProcessPacketType(
&mut self, packet_info.pdu_directive().unwrap(),
pdu_type: PduType, ));
pdu_directive: Option<FileDirectiveType>, }
raw_packet: &[u8], match packet_info.pdu_type {
) -> Result<(), DestError> {
match pdu_type {
PduType::FileDirective => { PduType::FileDirective => {
if pdu_directive.is_none() { if packet_info.pdu_directive.is_none() {
return Err(DestError::DirectiveExpected); return Err(DestError::DirectiveExpected);
} }
self.handle_file_directive(pdu_directive.unwrap(), raw_packet) self.handle_file_directive(
packet_info.pdu_directive.unwrap(),
packet_info.raw_packet,
)
} }
PduType::FileData => self.handle_file_data(raw_packet), PduType::FileData => self.handle_file_data(packet_info.raw_packet),
} }
} }
@ -262,6 +263,13 @@ impl DestinationHandler {
self.transaction_params.file_properties.dest_file_name_len = dest_name.len_value(); self.transaction_params.file_properties.dest_file_name_len = dest_name.len_value();
self.transaction_params.pdu_conf = *metadata_pdu.pdu_header().common_pdu_conf(); self.transaction_params.pdu_conf = *metadata_pdu.pdu_header().common_pdu_conf();
self.transaction_params.msgs_to_user_size = 0; self.transaction_params.msgs_to_user_size = 0;
if metadata_pdu.pdu_header().common_pdu_conf().trans_mode
== TransmissionMode::Unacknowledged
{
self.state = State::BusyClass1Nacked;
} else {
self.state = State::BusyClass2Acked;
}
if metadata_pdu.options().is_some() { if metadata_pdu.options().is_some() {
for option_tlv in metadata_pdu.options_iter().unwrap() { for option_tlv in metadata_pdu.options_iter().unwrap() {
if option_tlv.is_standard_tlv() if option_tlv.is_standard_tlv()
@ -459,6 +467,9 @@ impl DestinationHandler {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[allow(unused_imports)]
use std::println;
use spacepackets::{ use spacepackets::{
cfdp::{lv::Lv, ChecksumType}, cfdp::{lv::Lv, ChecksumType},
util::{UbfU16, UnsignedByteFieldU16}, util::{UbfU16, UnsignedByteFieldU16},
@ -556,12 +567,14 @@ mod tests {
#[test] #[test]
fn test_empty_file_transfer() { fn test_empty_file_transfer() {
let mut buf: [u8; 512] = [0; 512]; let mut buf: [u8; 512] = [0; 512];
let test_user = TestCfdpUser::default(); let mut test_user = TestCfdpUser::default();
let mut dest_handler = DestinationHandler::new(LOCAL_ID); let mut dest_handler = DestinationHandler::new(LOCAL_ID);
init_check(&dest_handler); init_check(&dest_handler);
let seq_num = UbfU16::new(0); let seq_num = UbfU16::new(0);
let pdu_conf = CommonPduConfig::new_with_byte_fields(REMOTE_ID, LOCAL_ID, seq_num).unwrap(); let mut pdu_conf =
CommonPduConfig::new_with_byte_fields(REMOTE_ID, LOCAL_ID, seq_num).unwrap();
pdu_conf.trans_mode = TransmissionMode::Unacknowledged;
let pdu_header = PduHeader::new_no_file_data(pdu_conf, 0); let pdu_header = PduHeader::new_no_file_data(pdu_conf, 0);
let metadata_params = MetadataGenericParams::new(false, ChecksumType::Crc32, 0); let metadata_params = MetadataGenericParams::new(false, ChecksumType::Crc32, 0);
let metadata_pdu = MetadataPdu::new( let metadata_pdu = MetadataPdu::new(
@ -574,11 +587,13 @@ mod tests {
let written_len = metadata_pdu let written_len = metadata_pdu
.write_to_bytes(&mut buf) .write_to_bytes(&mut buf)
.expect("writing metadata PDU failed"); .expect("writing metadata PDU failed");
// TODO: Create Metadata PDU and EOF PDU for empty file transfer. let packet_info =
dest_handler.insert_packet( PacketInfo::new(&buf[..written_len]).expect("generating packet info failed");
PduType::FileDirective, let insert_result = dest_handler.insert_packet(&packet_info);
Some(FileDirectiveType::MetadataPdu), if let Err(e) = insert_result {
&buf[..written_len], panic!("insert result error: {e}");
); }
let result = dest_handler.state_machine(&mut test_user);
assert!(result.is_ok());
} }
} }

View File

@ -1,11 +1,21 @@
use crc::{Crc, CRC_32_CKSUM}; use crc::{Crc, CRC_32_CKSUM};
use spacepackets::util::UnsignedByteField; use spacepackets::{
cfdp::{
pdu::{FileDirectiveType, PduError, PduHeader},
PduType,
},
util::UnsignedByteField,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub mod dest; pub mod dest;
pub mod user; pub mod user;
#[derive(Debug, PartialEq, Eq, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct TransactionId { pub struct TransactionId {
source_id: UnsignedByteField, source_id: UnsignedByteField,
seq_num: UnsignedByteField, seq_num: UnsignedByteField,
@ -26,6 +36,7 @@ impl TransactionId {
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum TransactionStep { pub enum TransactionStep {
Idle = 0, Idle = 0,
TransactionStart = 1, TransactionStart = 1,
@ -36,6 +47,7 @@ pub enum TransactionStep {
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum State { pub enum State {
Idle = 0, Idle = 0,
BusyClass1Nacked = 2, BusyClass1Nacked = 2,
@ -44,6 +56,105 @@ pub enum State {
pub const CRC_32: Crc<u32> = Crc::<u32>::new(&CRC_32_CKSUM); pub const CRC_32: Crc<u32> = Crc::<u32>::new(&CRC_32_CKSUM);
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum PacketTarget {
SourceEntity,
DestEntity,
}
/// This is a helper struct which contains base information about a particular PDU packet.
/// This is also necessary information for CFDP packet routing. For example, some packet types
/// like file data PDUs can only be used by CFDP source entities.
pub struct PacketInfo<'raw_packet> {
pdu_type: PduType,
pdu_directive: Option<FileDirectiveType>,
target: PacketTarget,
raw_packet: &'raw_packet [u8],
}
impl<'raw> PacketInfo<'raw> {
pub fn new(raw_packet: &'raw [u8]) -> Result<Self, PduError> {
let (pdu_header, header_len) = PduHeader::from_bytes(raw_packet)?;
if pdu_header.pdu_type() == PduType::FileData {
return Ok(Self {
pdu_type: pdu_header.pdu_type(),
pdu_directive: None,
target: PacketTarget::DestEntity,
raw_packet,
});
}
if pdu_header.pdu_datafield_len() < 1 {
return Err(PduError::FormatError);
}
// Route depending on PDU type and directive type if applicable. Retrieve directive type
// from the raw stream for better performance (with sanity and directive code check).
// The routing is based on section 4.5 of the CFDP standard which specifies the PDU forwarding
// procedure.
let directive = FileDirectiveType::try_from(raw_packet[header_len]).map_err(|_| {
PduError::InvalidDirectiveType {
found: raw_packet[header_len],
expected: None,
}
})?;
let packet_target = match directive {
// Section c) of 4.5.3: These PDUs should always be targeted towards the file sender a.k.a.
// the source handler
FileDirectiveType::NakPdu
| FileDirectiveType::FinishedPdu
| FileDirectiveType::KeepAlivePdu => PacketTarget::SourceEntity,
// Section b) of 4.5.3: These PDUs should always be targeted towards the file receiver a.k.a.
// the destination handler
FileDirectiveType::MetadataPdu
| FileDirectiveType::EofPdu
| FileDirectiveType::PromptPdu => PacketTarget::DestEntity,
// Section a): Recipient depends of the type of PDU that is being acknowledged. We can simply
// extract the PDU type from the raw stream. If it is an EOF PDU, this packet is passed to
// the source handler, for a Finished PDU, it is passed to the destination handler.
FileDirectiveType::AckPdu => {
let acked_directive = FileDirectiveType::try_from(raw_packet[header_len + 1])
.map_err(|_| PduError::InvalidDirectiveType {
found: raw_packet[header_len],
expected: None,
})?;
if acked_directive == FileDirectiveType::EofPdu {
PacketTarget::SourceEntity
} else if acked_directive == FileDirectiveType::FinishedPdu {
PacketTarget::DestEntity
} else {
// TODO: Maybe a better error? This might be confusing..
return Err(PduError::InvalidDirectiveType {
found: raw_packet[header_len + 1],
expected: None,
});
}
}
};
Ok(Self {
pdu_type: pdu_header.pdu_type(),
pdu_directive: Some(directive),
target: packet_target,
raw_packet,
})
}
pub fn pdu_type(&self) -> PduType {
self.pdu_type
}
pub fn pdu_directive(&self) -> Option<FileDirectiveType> {
self.pdu_directive
}
pub fn target(&self) -> PacketTarget {
self.target
}
pub fn raw_packet(&self) -> &[u8] {
self.raw_packet
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[test] #[test]