Skip to main content

leodos_protocols/transport/cfdp/class2/machine/sender/
action.rs

1use heapless::Vec;
2
3use crate::transport::cfdp::CfdpError;
4use crate::transport::cfdp::class2::machine::MAX_ACTIONS_PER_EVENT;
5use crate::transport::cfdp::class2::machine::PromptType;
6use crate::transport::cfdp::class2::machine::TimerType;
7use crate::transport::cfdp::class2::machine::TransactionId;
8use crate::transport::cfdp::filestore::FileId;
9use crate::transport::cfdp::pdu::EntityId;
10use crate::transport::cfdp::pdu::file_directive::ConditionCode;
11use crate::transport::cfdp::pdu::file_directive::ack::AckedDirectiveCode;
12use crate::transport::cfdp::pdu::file_directive::ack::TransactionStatus;
13use crate::transport::cfdp::pdu::file_directive::metadata::ChecksumType;
14use crate::transport::cfdp::pdu::file_directive::nak::NakSegmentsIterator;
15
16/// Represents all possible outputs from the `SenderMachine`.
17///
18/// These are instructions for the `Runner` to execute, such as sending PDUs,
19/// managing timers, or interacting with the filestore.
20#[derive(Debug)]
21pub enum Action<'a> {
22    /// Instructs the `Runner` to serialize and send a Metadata PDU.
23    SendMetadata {
24        /// Identifies the transaction this PDU belongs to.
25        transaction_id: TransactionId,
26        /// The remote entity to send this PDU to.
27        destination_id: EntityId,
28        /// Total size of the file being transferred in bytes.
29        file_size: u64,
30        /// Filestore identifier for the file on the sending side.
31        source_file_name: FileId,
32        /// Filestore identifier for the file on the receiving side.
33        destination_file_name: FileId,
34        /// Algorithm used to verify file integrity.
35        checksum_type: ChecksumType,
36    },
37    /// Instructs the `Runner` to serialize and send a File Data PDU.
38    SendFileData {
39        /// Identifies the transaction this PDU belongs to.
40        transaction_id: TransactionId,
41        /// The remote entity to send this PDU to.
42        destination_id: EntityId,
43        /// Byte offset within the file where this data begins.
44        offset: u64,
45        /// The file data segment payload.
46        data: &'a [u8],
47    },
48    /// Instructs the `Runner` to serialize and send an EOF PDU.
49    SendEof {
50        /// Identifies the transaction this PDU belongs to.
51        transaction_id: TransactionId,
52        /// The remote entity to send this PDU to.
53        destination_id: EntityId,
54        /// Status condition at the time the EOF is sent.
55        condition_code: ConditionCode,
56        /// Total size of the file in bytes.
57        file_size: u64,
58        /// Computed checksum of the complete file data.
59        checksum: u32,
60    },
61    /// Instructs the `Runner` to serialize and send a Finished PDU.
62    SendFinished {
63        /// Identifies the transaction this PDU belongs to.
64        transaction_id: TransactionId,
65        /// The remote entity to send this PDU to.
66        destination_id: EntityId,
67        /// Final status condition of the transaction.
68        condition_code: ConditionCode,
69    },
70    /// Instructs the `Runner` to serialize and send an ACK PDU.
71    SendAck {
72        /// Identifies the transaction this PDU belongs to.
73        transaction_id: TransactionId,
74        /// The remote entity to send this PDU to.
75        destination_id: EntityId,
76        /// The directive code being acknowledged.
77        acked_directive_code: AckedDirectiveCode,
78        /// Status condition associated with the acknowledgment.
79        condition_code: ConditionCode,
80        /// Current status of the transaction being acknowledged.
81        transaction_status: TransactionStatus,
82    },
83    /// Instructs the `Runner` to serialize and send a Prompt PDU.
84    SendPrompt {
85        /// Identifies the transaction this PDU belongs to.
86        transaction_id: TransactionId,
87        /// The remote entity to send this PDU to.
88        destination_id: EntityId,
89        /// Whether to prompt for a NAK or Keep Alive response.
90        prompt_type: PromptType,
91    },
92    /// Instructs the `Runner` to read a segment of data from the filestore.
93    ReadDataSegment {
94        /// Identifies the transaction this read belongs to.
95        transaction_id: TransactionId,
96        /// Byte offset where the segment begins.
97        start_offset: u64,
98        /// Byte offset where the segment ends (exclusive).
99        end_offset: u64,
100    },
101    /// Instructs the `Runner` to read multiple segments of data from the filestore.
102    ReadDataSegmentBatch {
103        /// Identifies the transaction this batch read belongs to.
104        transaction_id: TransactionId,
105        /// Iterator over the missing segments requested by the receiver.
106        segments: NakSegmentsIterator<'a>,
107    },
108    /// Instructs the `Runner` to start a timer for a specific transaction.
109    StartTimer {
110        /// Identifies the transaction this timer belongs to.
111        transaction_id: TransactionId,
112        /// The kind of timer to start (e.g. Ack, Nak, Inactivity).
113        timer_type: TimerType,
114        /// Duration of the timer in seconds.
115        seconds: u16,
116    },
117    /// Instructs the `Runner` to stop a timer for a specific transaction.
118    StopTimer {
119        /// Identifies the transaction this timer belongs to.
120        transaction_id: TransactionId,
121        /// The type of timer to stop. If `None`, stops all timers for the transaction.
122        timer_type: Option<TimerType>,
123    },
124    /// Instructs the `Runner` that a transaction is completed and can be cleaned up.
125    TerminateTransaction {
126        /// Identifies the transaction to terminate.
127        transaction_id: TransactionId,
128        /// Final status condition describing why the transaction ended.
129        condition_code: ConditionCode,
130    },
131    /// Instructs the `Runner` to calculate a checksum for a transaction.
132    CalculateChecksum {
133        /// Identifies the transaction to compute the checksum for.
134        transaction_id: TransactionId,
135        /// Algorithm to use for the checksum calculation.
136        checksum_type: ChecksumType,
137    },
138    /// Instructs the `Runner` to notify the user that a fault has occurred.
139    NotifyFault {
140        /// Identifies the faulted transaction.
141        transaction_id: TransactionId,
142        /// The condition that caused the fault.
143        condition_code: ConditionCode,
144    },
145    /// Instructs the `Runner` to notify the user that a transaction was suspended.
146    NotifySuspended {
147        /// Identifies the suspended transaction.
148        transaction_id: TransactionId,
149    },
150    /// Instructs the `Runner` to notify the user that a transaction was resumed.
151    NotifyResumed {
152        /// Identifies the resumed transaction.
153        transaction_id: TransactionId,
154        /// Number of bytes successfully transferred before suspension.
155        progress: u64,
156    },
157}
158
159/// A bounded collection of actions produced by processing a single event.
160pub struct Actions<'a> {
161    /// The bounded buffer of actions.
162    actions: Vec<Action<'a>, MAX_ACTIONS_PER_EVENT, u8>,
163}
164
165impl<'a> Actions<'a> {
166    /// Creates an empty `Actions` collection.
167    pub fn new() -> Self {
168        Actions {
169            actions: Vec::new(),
170        }
171    }
172
173    /// Adds an action to the collection.
174    pub fn push(&mut self, action: Action<'a>) -> Result<(), CfdpError> {
175        self.actions
176            .push(action)
177            .map_err(|_| CfdpError::ActionBufferFull)
178    }
179
180    /// Returns an iterator over the actions.
181    pub fn iter(&self) -> impl Iterator<Item = &Action<'a>> {
182        self.actions.iter()
183    }
184
185    /// Removes all actions from the collection.
186    pub fn clear(&mut self) {
187        self.actions.clear();
188    }
189}
190
191impl<'a> Iterator for Actions<'a> {
192    type Item = Action<'a>;
193
194    fn next(&mut self) -> Option<Self::Item> {
195        self.actions.pop()
196    }
197}