continue
This commit is contained in:
150
src/dest.rs
150
src/dest.rs
@@ -30,36 +30,36 @@
|
|||||||
//! 4. A Finished PDU has been sent back to the remote side.
|
//! 4. A Finished PDU has been sent back to the remote side.
|
||||||
//! 5. A Finished PDU ACK was received.
|
//! 5. A Finished PDU ACK was received.
|
||||||
use crate::{
|
use crate::{
|
||||||
DummyPduProvider, GenericSendError, IndicationConfig, PduProvider, PositiveAckParams,
|
|
||||||
lost_segments::{LostSegmentError, LostSegmentStore},
|
lost_segments::{LostSegmentError, LostSegmentStore},
|
||||||
user::TransactionFinishedParams,
|
user::TransactionFinishedParams,
|
||||||
|
DummyPduProvider, GenericSendError, IndicationConfig, PduProvider, PositiveAckParams,
|
||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
str::{Utf8Error, from_utf8, from_utf8_unchecked},
|
str::{from_utf8, from_utf8_unchecked, Utf8Error},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Countdown, EntityType, LocalEntityConfig, PacketTarget, PduSendProvider, RemoteConfigStore,
|
|
||||||
RemoteEntityConfig, State, TimerContext, TimerCreator, TransactionId, UserFaultHook,
|
|
||||||
filestore::{FilestoreError, VirtualFilestore},
|
filestore::{FilestoreError, VirtualFilestore},
|
||||||
user::{CfdpUser, FileSegmentRecvdParams, MetadataReceivedParams},
|
user::{CfdpUser, FileSegmentRecvdParams, MetadataReceivedParams},
|
||||||
|
Countdown, EntityType, LocalEntityConfig, PacketTarget, PduSender, RemoteConfigStore,
|
||||||
|
RemoteEntityConfig, State, TimerContext, TimerCreator, TransactionId, UserFaultHook,
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use spacepackets::{
|
use spacepackets::{
|
||||||
cfdp::{
|
cfdp::{
|
||||||
ChecksumType, ConditionCode, FaultHandlerCode, LargeFileFlag, PduType, TransactionStatus,
|
|
||||||
TransmissionMode,
|
|
||||||
pdu::{
|
pdu::{
|
||||||
CfdpPdu, CommonPduConfig, FileDirectiveType, PduError, PduHeader,
|
|
||||||
ack::AckPdu,
|
ack::AckPdu,
|
||||||
eof::EofPdu,
|
eof::EofPdu,
|
||||||
file_data::FileDataPdu,
|
file_data::FileDataPdu,
|
||||||
finished::{DeliveryCode, FileStatus, FinishedPduCreator},
|
finished::{DeliveryCode, FileStatus, FinishedPduCreator},
|
||||||
metadata::{MetadataGenericParams, MetadataPduReader},
|
metadata::{MetadataGenericParams, MetadataPduReader},
|
||||||
nak::NakPduCreatorWithReservedSeqReqsBuf,
|
nak::NakPduCreatorWithReservedSeqReqsBuf,
|
||||||
|
CfdpPdu, CommonPduConfig, FileDirectiveType, PduError, PduHeader,
|
||||||
},
|
},
|
||||||
tlv::{EntityIdTlv, GenericTlv, ReadableTlv, TlvType, msg_to_user::MsgToUserTlv},
|
tlv::{msg_to_user::MsgToUserTlv, EntityIdTlv, GenericTlv, ReadableTlv, TlvType},
|
||||||
|
ChecksumType, ConditionCode, FaultHandlerCode, LargeFileFlag, PduType, TransactionStatus,
|
||||||
|
TransmissionMode,
|
||||||
},
|
},
|
||||||
util::{UnsignedByteField, UnsignedEnum},
|
util::{UnsignedByteField, UnsignedEnum},
|
||||||
};
|
};
|
||||||
@@ -334,9 +334,9 @@ pub enum DestError {
|
|||||||
/// in different concurrent contexts. For example, you can dynamically create new handlers and
|
/// in different concurrent contexts. For example, you can dynamically create new handlers and
|
||||||
/// run them inside a thread pool, or move the newly created handler to a new thread."""
|
/// run them inside a thread pool, or move the newly created handler to a new thread."""
|
||||||
pub struct DestinationHandler<
|
pub struct DestinationHandler<
|
||||||
PduSender: PduSendProvider,
|
PduSenderInstance: PduSender,
|
||||||
UserFaultHookInstance: UserFaultHook,
|
UserFaultHookInstance: UserFaultHook,
|
||||||
Vfs: VirtualFilestore,
|
VirtualFileStoreInstance: VirtualFilestore,
|
||||||
RemoteConfigStoreInstance: RemoteConfigStore,
|
RemoteConfigStoreInstance: RemoteConfigStore,
|
||||||
TimerCreatorInstance: TimerCreator<Countdown = CountdownInstance>,
|
TimerCreatorInstance: TimerCreator<Countdown = CountdownInstance>,
|
||||||
CountdownInstance: Countdown,
|
CountdownInstance: Countdown,
|
||||||
@@ -347,8 +347,8 @@ pub struct DestinationHandler<
|
|||||||
state: State,
|
state: State,
|
||||||
transaction_params: TransactionParams<CountdownInstance>,
|
transaction_params: TransactionParams<CountdownInstance>,
|
||||||
pdu_and_cksum_buffer: RefCell<alloc::vec::Vec<u8>>,
|
pdu_and_cksum_buffer: RefCell<alloc::vec::Vec<u8>>,
|
||||||
pub pdu_sender: PduSender,
|
pub pdu_sender: PduSenderInstance,
|
||||||
pub vfs: Vfs,
|
pub vfs: VirtualFileStoreInstance,
|
||||||
pub remote_cfg_table: RemoteConfigStoreInstance,
|
pub remote_cfg_table: RemoteConfigStoreInstance,
|
||||||
pub check_timer_creator: TimerCreatorInstance,
|
pub check_timer_creator: TimerCreatorInstance,
|
||||||
lost_segment_tracker: LostSegmentTracker,
|
lost_segment_tracker: LostSegmentTracker,
|
||||||
@@ -366,14 +366,14 @@ pub type StdDestinationHandler<PduSender, UserFaultHook> = DestinationHandler<
|
|||||||
>;
|
>;
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<PduSender: PduSendProvider, UserFaultHookInstance: UserFaultHook>
|
impl<PduSenderInstance: PduSender, UserFaultHookInstance: UserFaultHook>
|
||||||
StdDestinationHandler<PduSender, UserFaultHookInstance>
|
StdDestinationHandler<PduSenderInstance, UserFaultHookInstance>
|
||||||
{
|
{
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn new_std(
|
pub fn new_std(
|
||||||
local_cfg: LocalEntityConfig<UserFaultHookInstance>,
|
local_cfg: LocalEntityConfig<UserFaultHookInstance>,
|
||||||
pdu_and_cksum_buf_size: usize,
|
pdu_and_cksum_buf_size: usize,
|
||||||
pdu_sender: PduSender,
|
pdu_sender: PduSenderInstance,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new(
|
Self::new(
|
||||||
local_cfg,
|
local_cfg,
|
||||||
@@ -388,18 +388,18 @@ impl<PduSender: PduSendProvider, UserFaultHookInstance: UserFaultHook>
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
PduSender: PduSendProvider,
|
PduSenderInstance: PduSender,
|
||||||
UserFaultHookInstance: UserFaultHook,
|
UserFaultHookInstance: UserFaultHook,
|
||||||
Vfs: VirtualFilestore,
|
VirtualFilestoreInstance: VirtualFilestore,
|
||||||
RemoteConfigStoreInstance: RemoteConfigStore,
|
RemoteConfigStoreInstance: RemoteConfigStore,
|
||||||
TimerCreatorInstance: TimerCreator<Countdown = CountdownInstance>,
|
TimerCreatorInstance: TimerCreator<Countdown = CountdownInstance>,
|
||||||
CountdownInstance: Countdown,
|
CountdownInstance: Countdown,
|
||||||
LostSegmentTracker: LostSegmentStore,
|
LostSegmentTracker: LostSegmentStore,
|
||||||
>
|
>
|
||||||
DestinationHandler<
|
DestinationHandler<
|
||||||
PduSender,
|
PduSenderInstance,
|
||||||
UserFaultHookInstance,
|
UserFaultHookInstance,
|
||||||
Vfs,
|
VirtualFilestoreInstance,
|
||||||
RemoteConfigStoreInstance,
|
RemoteConfigStoreInstance,
|
||||||
TimerCreatorInstance,
|
TimerCreatorInstance,
|
||||||
CountdownInstance,
|
CountdownInstance,
|
||||||
@@ -429,8 +429,8 @@ impl<
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
local_cfg: LocalEntityConfig<UserFaultHookInstance>,
|
local_cfg: LocalEntityConfig<UserFaultHookInstance>,
|
||||||
pdu_and_cksum_buf_size: usize,
|
pdu_and_cksum_buf_size: usize,
|
||||||
pdu_sender: PduSender,
|
pdu_sender: PduSenderInstance,
|
||||||
vfs: Vfs,
|
vfs: VirtualFilestoreInstance,
|
||||||
remote_cfg_table: RemoteConfigStoreInstance,
|
remote_cfg_table: RemoteConfigStoreInstance,
|
||||||
timer_creator: TimerCreatorInstance,
|
timer_creator: TimerCreatorInstance,
|
||||||
lost_segment_tracker: LostSegmentTracker,
|
lost_segment_tracker: LostSegmentTracker,
|
||||||
@@ -987,6 +987,48 @@ impl<
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deferred_lost_segment_handling(&mut self) {
|
||||||
|
assert!(
|
||||||
|
self.transaction_params.acked_params.is_some(),
|
||||||
|
"acknowledged parameters unexpectedly None"
|
||||||
|
);
|
||||||
|
let acked_params = self.transaction_params.acked_params.as_mut().unwrap();
|
||||||
|
if self.lost_segment_tracker.is_empty() && !acked_params.metadata_missing {
|
||||||
|
// We are done and have received everything.
|
||||||
|
match self.checksum_verify(
|
||||||
|
self.transaction_params.progress,
|
||||||
|
self.transaction_params.checksum,
|
||||||
|
) {
|
||||||
|
true => {
|
||||||
|
self.transaction_params
|
||||||
|
.finished_params
|
||||||
|
.condition_code
|
||||||
|
.set(ConditionCode::NoError);
|
||||||
|
self.transaction_params
|
||||||
|
.finished_params
|
||||||
|
.delivery_code
|
||||||
|
.set(DeliveryCode::Complete);
|
||||||
|
}
|
||||||
|
false => {
|
||||||
|
self.transaction_params
|
||||||
|
.finished_params
|
||||||
|
.condition_code
|
||||||
|
.set(ConditionCode::FileChecksumFailure);
|
||||||
|
self.transaction_params
|
||||||
|
.finished_params
|
||||||
|
.delivery_code
|
||||||
|
.set(DeliveryCode::Incomplete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.set_step(TransactionStep::TransferCompletion);
|
||||||
|
acked_params.deferred_procedure_active = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut first_nak_issuance = self.transaction_params.deferred_procedure_timer.is_none();
|
||||||
|
if first_nak_issuance {
|
||||||
self.transaction_params.deferred_procedure_timer = Some(
|
self.transaction_params.deferred_procedure_timer = Some(
|
||||||
self.check_timer_creator
|
self.check_timer_creator
|
||||||
.create_countdown(TimerContext::NakActivity {
|
.create_countdown(TimerContext::NakActivity {
|
||||||
@@ -998,9 +1040,57 @@ impl<
|
|||||||
.nak_timer_interval,
|
.nak_timer_interval,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
} else if !self
|
||||||
|
.transaction_params
|
||||||
|
.deferred_procedure_timer
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.has_expired()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if !first_nak_issuance
|
||||||
|
&& acked_params.nak_activity_counter + 1
|
||||||
|
== self
|
||||||
|
.transaction_params
|
||||||
|
.remote_cfg
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.nak_timer_expiration_limit
|
||||||
|
{
|
||||||
|
self.transaction_params.finished_params.delivery_code = DeliveryCode::Incomplete;
|
||||||
|
if self.declare_fault(ConditionCode::NakLimitReached)
|
||||||
|
== FaultHandlerCode::AbandonTransaction
|
||||||
|
{
|
||||||
|
self.abandon_transaction();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let pdu_header = PduHeader::new_no_file_data(self.transaction_params.pdu_conf, 0);
|
||||||
|
let max_segment_reqs = NakPduCreatorWithReservedSeqReqsBuf::calculate_max_segment_requests(
|
||||||
|
self.transaction_params
|
||||||
|
.remote_cfg
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.max_packet_len,
|
||||||
|
&pdu_header,
|
||||||
|
);
|
||||||
|
let mut segments_to_send = self.lost_segment_tracker.number_of_segments();
|
||||||
|
if acked_params.metadata_missing {
|
||||||
|
segments_to_send += 1;
|
||||||
|
}
|
||||||
|
if segments_to_send <= max_segment_reqs {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deferred_lost_segment_handling(&mut self) {
|
let mut nak_pdu_creator = NakPduCreatorWithReservedSeqReqsBuf::new(
|
||||||
|
self.pdu_and_cksum_buffer.get_mut(),
|
||||||
|
pdu_header,
|
||||||
|
core::cmp::min(segments_to_send as usize, max_segment_reqs),
|
||||||
|
)
|
||||||
|
for index in 0..segments_to_send {
|
||||||
|
|
||||||
|
}
|
||||||
// TODO.
|
// TODO.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1511,21 +1601,21 @@ mod tests {
|
|||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use spacepackets::{
|
use spacepackets::{
|
||||||
cfdp::{
|
cfdp::{
|
||||||
ChecksumType, TransmissionMode,
|
|
||||||
lv::Lv,
|
lv::Lv,
|
||||||
pdu::{WritablePduPacket, finished::FinishedPduReader, metadata::MetadataPduCreator},
|
pdu::{finished::FinishedPduReader, metadata::MetadataPduCreator, WritablePduPacket},
|
||||||
|
ChecksumType, TransmissionMode,
|
||||||
},
|
},
|
||||||
util::{UbfU16, UnsignedByteFieldU8},
|
util::{UbfU16, UnsignedByteFieldU8},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
CRC_32, FaultHandler, IndicationConfig, PduRawWithInfo, RemoteConfigStoreStd,
|
|
||||||
filestore::NativeFilestore,
|
filestore::NativeFilestore,
|
||||||
lost_segments::LostSegmentsList,
|
lost_segments::LostSegmentsList,
|
||||||
tests::{
|
tests::{
|
||||||
LOCAL_ID, REMOTE_ID, SentPdu, TestCfdpSender, TestCfdpUser, TestCheckTimer,
|
basic_remote_cfg_table, SentPdu, TestCfdpSender, TestCfdpUser, TestCheckTimer,
|
||||||
TestCheckTimerCreator, TestFaultHandler, TimerExpiryControl, basic_remote_cfg_table,
|
TestCheckTimerCreator, TestFaultHandler, TimerExpiryControl, LOCAL_ID, REMOTE_ID,
|
||||||
},
|
},
|
||||||
|
FaultHandler, IndicationConfig, PduRawWithInfo, RemoteConfigStoreStd, CRC_32,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -1842,14 +1932,12 @@ mod tests {
|
|||||||
let dest_handler =
|
let dest_handler =
|
||||||
default_dest_handler(fault_handler, test_sender, &TimerExpiryControl::default());
|
default_dest_handler(fault_handler, test_sender, &TimerExpiryControl::default());
|
||||||
assert!(dest_handler.transmission_mode().is_none());
|
assert!(dest_handler.transmission_mode().is_none());
|
||||||
assert!(
|
assert!(dest_handler
|
||||||
dest_handler
|
|
||||||
.local_cfg
|
.local_cfg
|
||||||
.fault_handler
|
.fault_handler
|
||||||
.user_hook
|
.user_hook
|
||||||
.borrow()
|
.borrow()
|
||||||
.all_queues_empty()
|
.all_queues_empty());
|
||||||
);
|
|
||||||
assert!(dest_handler.pdu_sender.queue_empty());
|
assert!(dest_handler.pdu_sender.queue_empty());
|
||||||
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);
|
||||||
|
|||||||
@@ -693,7 +693,7 @@ pub enum GenericSendError {
|
|||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PduSendProvider {
|
pub trait PduSender {
|
||||||
fn send_pdu(
|
fn send_pdu(
|
||||||
&self,
|
&self,
|
||||||
pdu_type: PduType,
|
pdu_type: PduType,
|
||||||
@@ -716,7 +716,7 @@ pub mod std_mod {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
impl PduSendProvider for mpsc::Sender<PduOwnedWithInfo> {
|
impl PduSender for mpsc::Sender<PduOwnedWithInfo> {
|
||||||
fn send_pdu(
|
fn send_pdu(
|
||||||
&self,
|
&self,
|
||||||
pdu_type: PduType,
|
pdu_type: PduType,
|
||||||
@@ -1471,7 +1471,7 @@ pub(crate) mod tests {
|
|||||||
pub packet_queue: RefCell<VecDeque<SentPdu>>,
|
pub packet_queue: RefCell<VecDeque<SentPdu>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PduSendProvider for TestCfdpSender {
|
impl PduSender for TestCfdpSender {
|
||||||
fn send_pdu(
|
fn send_pdu(
|
||||||
&self,
|
&self,
|
||||||
pdu_type: PduType,
|
pdu_type: PduType,
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
LocalEntityConfig, PacketTarget, PduSendProvider, RemoteConfigStore, RemoteEntityConfig, State,
|
LocalEntityConfig, PacketTarget, PduSender, RemoteConfigStore, RemoteEntityConfig, State,
|
||||||
TransactionId, UserFaultHook,
|
TransactionId, UserFaultHook,
|
||||||
filestore::{FilestoreError, VirtualFilestore},
|
filestore::{FilestoreError, VirtualFilestore},
|
||||||
request::{ReadablePutRequest, StaticPutRequestCacher},
|
request::{ReadablePutRequest, StaticPutRequestCacher},
|
||||||
@@ -242,7 +242,7 @@ pub enum FsmContext {
|
|||||||
/// is required, it is recommended to create a new handler and run all active handlers inside a
|
/// is required, it is recommended to create a new handler and run all active handlers inside a
|
||||||
/// thread pool, or move the newly created handler to a new thread.
|
/// thread pool, or move the newly created handler to a new thread.
|
||||||
pub struct SourceHandler<
|
pub struct SourceHandler<
|
||||||
PduSender: PduSendProvider,
|
PduSenderInstance: PduSender,
|
||||||
UserFaultHookInstance: UserFaultHook,
|
UserFaultHookInstance: UserFaultHook,
|
||||||
Vfs: VirtualFilestore,
|
Vfs: VirtualFilestore,
|
||||||
RemoteConfigStoreInstance: RemoteConfigStore,
|
RemoteConfigStoreInstance: RemoteConfigStore,
|
||||||
@@ -251,7 +251,7 @@ pub struct SourceHandler<
|
|||||||
SequenceCounterInstance: SequenceCounter,
|
SequenceCounterInstance: SequenceCounter,
|
||||||
> {
|
> {
|
||||||
local_cfg: LocalEntityConfig<UserFaultHookInstance>,
|
local_cfg: LocalEntityConfig<UserFaultHookInstance>,
|
||||||
pdu_sender: PduSender,
|
pdu_sender: PduSenderInstance,
|
||||||
pdu_and_cksum_buffer: RefCell<alloc::vec::Vec<u8>>,
|
pdu_and_cksum_buffer: RefCell<alloc::vec::Vec<u8>>,
|
||||||
put_request_cacher: StaticPutRequestCacher,
|
put_request_cacher: StaticPutRequestCacher,
|
||||||
remote_cfg_table: RemoteConfigStoreInstance,
|
remote_cfg_table: RemoteConfigStoreInstance,
|
||||||
@@ -271,7 +271,7 @@ pub struct SourceHandler<
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
PduSender: PduSendProvider,
|
PduSenderInstance: PduSender,
|
||||||
UserFaultHookInstance: UserFaultHook,
|
UserFaultHookInstance: UserFaultHook,
|
||||||
Vfs: VirtualFilestore,
|
Vfs: VirtualFilestore,
|
||||||
RemoteConfigStoreInstance: RemoteConfigStore,
|
RemoteConfigStoreInstance: RemoteConfigStore,
|
||||||
@@ -280,7 +280,7 @@ impl<
|
|||||||
SequenceCounterInstance: SequenceCounter,
|
SequenceCounterInstance: SequenceCounter,
|
||||||
>
|
>
|
||||||
SourceHandler<
|
SourceHandler<
|
||||||
PduSender,
|
PduSenderInstance,
|
||||||
UserFaultHookInstance,
|
UserFaultHookInstance,
|
||||||
Vfs,
|
Vfs,
|
||||||
RemoteConfigStoreInstance,
|
RemoteConfigStoreInstance,
|
||||||
@@ -314,7 +314,7 @@ impl<
|
|||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
cfg: LocalEntityConfig<UserFaultHookInstance>,
|
cfg: LocalEntityConfig<UserFaultHookInstance>,
|
||||||
pdu_sender: PduSender,
|
pdu_sender: PduSenderInstance,
|
||||||
vfs: Vfs,
|
vfs: Vfs,
|
||||||
put_request_cacher: StaticPutRequestCacher,
|
put_request_cacher: StaticPutRequestCacher,
|
||||||
pdu_and_cksum_buf_size: usize,
|
pdu_and_cksum_buf_size: usize,
|
||||||
|
|||||||
Reference in New Issue
Block a user