changes for spacepackets update
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-10 20:24:47 +02:00
parent 95a1295718
commit 05391bbafe
Signed by: muellerr
GPG Key ID: 407F9B00F858F270

View File

@ -6,23 +6,35 @@ use std::{
}; };
use super::{State, TransactionStep, CRC_32}; use super::{State, TransactionStep, CRC_32};
use spacepackets::cfdp::{ use spacepackets::{
cfdp::{
pdu::{ pdu::{
eof::EofPdu, eof::EofPdu,
file_data::FileDataPdu, file_data::FileDataPdu,
finished::DeliveryCode, finished::{DeliveryCode, FileStatus, FinishedPdu},
metadata::{MetadataGenericParams, MetadataPdu}, metadata::{MetadataGenericParams, MetadataPdu},
CommonPduConfig, FileDirectiveType, PduError, CommonPduConfig, FileDirectiveType, PduError, PduHeader,
}, },
tlv::EntityIdTlv,
ConditionCode, PduType, ConditionCode, PduType,
},
util::UnsignedByteField,
}; };
use thiserror::Error; use thiserror::Error;
pub struct DestinationHandler { pub struct DestinationHandler {
id: UnsignedByteField,
step: TransactionStep, step: TransactionStep,
state: State, state: State,
pdu_conf: CommonPduConfig, pdu_conf: CommonPduConfig,
transaction_params: TransactionParams, transaction_params: TransactionParams,
packets_to_send_ctx: PacketsToSendContext,
}
#[derive(Debug, Default)]
struct PacketsToSendContext {
packet_available: bool,
directive: Option<FileDirectiveType>,
} }
struct TransactionParams { struct TransactionParams {
@ -34,6 +46,7 @@ struct TransactionParams {
dest_path_buf: PathBuf, dest_path_buf: PathBuf,
condition_code: ConditionCode, condition_code: ConditionCode,
delivery_code: DeliveryCode, delivery_code: DeliveryCode,
file_status: FileStatus,
cksum_buf: [u8; 1024], cksum_buf: [u8; 1024],
} }
@ -48,6 +61,7 @@ impl Default for TransactionParams {
dest_path_buf: Default::default(), dest_path_buf: Default::default(),
condition_code: ConditionCode::NoError, condition_code: ConditionCode::NoError,
delivery_code: DeliveryCode::Incomplete, delivery_code: DeliveryCode::Incomplete,
file_status: FileStatus::Unreported,
cksum_buf: [0; 1024], cksum_buf: [0; 1024],
} }
} }
@ -87,12 +101,14 @@ pub enum DestError {
} }
impl DestinationHandler { impl DestinationHandler {
pub fn new() -> Self { pub fn new(id: impl Into<UnsignedByteField>) -> Self {
Self { Self {
id: id.into(),
step: TransactionStep::Idle, step: TransactionStep::Idle,
state: State::Idle, state: State::Idle,
pdu_conf: CommonPduConfig::new_with_defaults(), pdu_conf: Default::default(),
transaction_params: Default::default(), transaction_params: Default::default(),
packets_to_send_ctx: Default::default(),
} }
} }
@ -121,6 +137,55 @@ impl DestinationHandler {
} }
} }
pub fn packet_to_send_ready(&self) -> bool {
self.packets_to_send_ctx.packet_available
}
pub fn get_next_packet_to_send(
&self,
buf: &mut [u8],
) -> Result<Option<(FileDirectiveType, usize)>, DestError> {
if !self.packet_to_send_ready() {
return Ok(None);
}
let directive = self.packets_to_send_ctx.directive.unwrap();
let mut writte_size = 0;
match directive {
FileDirectiveType::EofPdu => todo!(),
FileDirectiveType::FinishedPdu => {
let pdu_header = PduHeader::new_no_file_data(self.pdu_conf, 0);
let finished_pdu = if self.transaction_params.condition_code
== ConditionCode::NoError
|| self.transaction_params.condition_code
== ConditionCode::UnsupportedChecksumType
{
FinishedPdu::new_default(
pdu_header,
self.transaction_params.delivery_code,
self.transaction_params.file_status,
)
} else {
// TODO: Are there cases where this ID is actually the source entity ID?
let entity_id = EntityIdTlv::new(self.id);
FinishedPdu::new_with_error(
pdu_header,
self.transaction_params.condition_code,
self.transaction_params.delivery_code,
self.transaction_params.file_status,
entity_id,
)
};
writte_size = finished_pdu.write_to_bytes(buf)?;
}
FileDirectiveType::AckPdu => todo!(),
FileDirectiveType::MetadataPdu => todo!(),
FileDirectiveType::NakPdu => todo!(),
FileDirectiveType::PromptPdu => todo!(),
FileDirectiveType::KeepAlivePdu => todo!(),
}
Ok(Some((directive, writte_size)))
}
pub fn handle_file_directive( pub fn handle_file_directive(
&mut self, &mut self,
pdu_directive: FileDirectiveType, pdu_directive: FileDirectiveType,
@ -180,13 +245,22 @@ impl DestinationHandler {
dest_file.write_all(fd_pdu.file_data())?; dest_file.write_all(fd_pdu.file_data())?;
Ok(()) Ok(())
} }
pub fn handle_eof_pdu(&mut self, raw_packet: &[u8]) -> Result<(), DestError> { pub fn handle_eof_pdu(&mut self, raw_packet: &[u8]) -> Result<(), DestError> {
if self.state == State::Idle || self.step != TransactionStep::ReceivingFileDataPdus { if self.state == State::Idle || self.step != TransactionStep::ReceivingFileDataPdus {
return Err(DestError::WrongStateForFileDataAndEof); return Err(DestError::WrongStateForFileDataAndEof);
} }
let eof_pdu = EofPdu::from_bytes(raw_packet)?; let eof_pdu = EofPdu::from_bytes(raw_packet)?;
let checksum = eof_pdu.file_checksum(); let checksum = eof_pdu.file_checksum();
self.checksum_check(checksum)?; // For a standard disk based file system, which is assumed to be used for now, the file
// will always be retained. This might change in the future.
self.transaction_params.file_status = FileStatus::Retained;
if self.checksum_check(checksum)? {
self.transaction_params.condition_code = ConditionCode::NoError;
self.transaction_params.delivery_code = DeliveryCode::Complete;
} else {
self.transaction_params.condition_code = ConditionCode::FileChecksumFailure;
}
if self.state == State::BusyClass1Nacked { if self.state == State::BusyClass1Nacked {
self.step = TransactionStep::TransferCompletion; self.step = TransactionStep::TransferCompletion;
} else { } else {
@ -200,7 +274,7 @@ impl DestinationHandler {
Ok(()) Ok(())
} }
fn checksum_check(&mut self, expected_checksum: u32) -> Result<(), DestError> { fn checksum_check(&mut self, expected_checksum: u32) -> Result<bool, DestError> {
let mut digest = CRC_32.digest(); let mut digest = CRC_32.digest();
let file_to_check = File::open(&self.transaction_params.dest_path_buf)?; let file_to_check = File::open(&self.transaction_params.dest_path_buf)?;
let mut buf_reader = BufReader::new(file_to_check); let mut buf_reader = BufReader::new(file_to_check);
@ -212,12 +286,9 @@ impl DestinationHandler {
digest.update(&self.transaction_params.cksum_buf[0..bytes_read]); digest.update(&self.transaction_params.cksum_buf[0..bytes_read]);
} }
if digest.finalize() == expected_checksum { if digest.finalize() == expected_checksum {
self.transaction_params.condition_code = ConditionCode::NoError; return Ok(true);
self.transaction_params.delivery_code = DeliveryCode::Complete;
} else {
self.transaction_params.condition_code = ConditionCode::FileChecksumFailure;
} }
Ok(()) Ok(false)
} }
fn fsm_nacked(&mut self) -> Result<(), DestError> { fn fsm_nacked(&mut self) -> Result<(), DestError> {
@ -236,7 +307,7 @@ impl DestinationHandler {
} }
TransactionStep::SendingAckPdu => todo!(), TransactionStep::SendingAckPdu => todo!(),
TransactionStep::SendingFinishedPdu => { TransactionStep::SendingFinishedPdu => {
self.send_finished_pdu()?; self.prepare_finished_pdu()?;
} }
} }
Ok(()) Ok(())
@ -288,18 +359,23 @@ impl DestinationHandler {
Ok(()) Ok(())
} }
fn send_finished_pdu(&mut self) -> Result<(), DestError> { fn prepare_finished_pdu(&mut self) -> Result<(), DestError> {
self.packets_to_send_ctx.packet_available = true;
self.packets_to_send_ctx.directive = Some(FileDirectiveType::FinishedPdu);
Ok(()) Ok(())
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use spacepackets::util::UnsignedByteFieldU8;
use super::*; use super::*;
#[test] #[test]
fn test_basic() { fn test_basic() {
let dest_handler = DestinationHandler::new(); let test_id = UnsignedByteFieldU8::new(1);
let dest_handler = DestinationHandler::new(test_id);
assert_eq!(dest_handler.state(), State::Idle); assert_eq!(dest_handler.state(), State::Idle);
assert_eq!(dest_handler.step(), TransactionStep::Idle); assert_eq!(dest_handler.step(), TransactionStep::Idle);
} }