changes for spacepackets update
Some checks failed
Rust/sat-rs/pipeline/pr-main There was a failure building this commit
Some checks failed
Rust/sat-rs/pipeline/pr-main There was a failure building this commit
This commit is contained in:
parent
95a1295718
commit
05391bbafe
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user