1use crate::tmtc::{ReceivesCcsdsTc, ReceivesTcCore};
89use alloc::boxed::Box;
90use core::fmt::{Display, Formatter};
91use downcast_rs::Downcast;
92use spacepackets::{ByteConversionError, CcsdsPacket, SpHeader};
93#[cfg(feature = "std")]
94use std::error::Error;
95
96pub trait CcsdsPacketHandler: Downcast {
107 type Error;
108
109 fn valid_apids(&self) -> &'static [u16];
110 fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8])
111 -> Result<(), Self::Error>;
112 fn handle_unknown_apid(
113 &mut self,
114 sp_header: &SpHeader,
115 tc_raw: &[u8],
116 ) -> Result<(), Self::Error>;
117}
118
119downcast_rs::impl_downcast!(CcsdsPacketHandler assoc Error);
120
121pub trait SendableCcsdsPacketHandler: CcsdsPacketHandler + Send {}
122
123impl<T: CcsdsPacketHandler + Send> SendableCcsdsPacketHandler for T {}
124
125downcast_rs::impl_downcast!(SendableCcsdsPacketHandler assoc Error);
126
127pub struct CcsdsDistributor<E> {
132 pub apid_handler: Box<dyn SendableCcsdsPacketHandler<Error = E>>,
136}
137
138#[derive(Debug, Copy, Clone, PartialEq, Eq)]
139pub enum CcsdsError<E> {
140 CustomError(E),
141 ByteConversionError(ByteConversionError),
142}
143
144impl<E: Display> Display for CcsdsError<E> {
145 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
146 match self {
147 Self::CustomError(e) => write!(f, "{e}"),
148 Self::ByteConversionError(e) => write!(f, "{e}"),
149 }
150 }
151}
152
153#[cfg(feature = "std")]
154impl<E: Error> Error for CcsdsError<E> {
155 fn source(&self) -> Option<&(dyn Error + 'static)> {
156 match self {
157 Self::CustomError(e) => e.source(),
158 Self::ByteConversionError(e) => e.source(),
159 }
160 }
161}
162
163impl<E: 'static> ReceivesCcsdsTc for CcsdsDistributor<E> {
164 type Error = CcsdsError<E>;
165
166 fn pass_ccsds(&mut self, header: &SpHeader, tc_raw: &[u8]) -> Result<(), Self::Error> {
167 self.dispatch_ccsds(header, tc_raw)
168 }
169}
170
171impl<E: 'static> ReceivesTcCore for CcsdsDistributor<E> {
172 type Error = CcsdsError<E>;
173
174 fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error> {
175 if tc_raw.len() < 7 {
176 return Err(CcsdsError::ByteConversionError(
177 ByteConversionError::FromSliceTooSmall {
178 found: tc_raw.len(),
179 expected: 7,
180 },
181 ));
182 }
183 let (sp_header, _) =
184 SpHeader::from_be_bytes(tc_raw).map_err(|e| CcsdsError::ByteConversionError(e))?;
185 self.dispatch_ccsds(&sp_header, tc_raw)
186 }
187}
188
189impl<E: 'static> CcsdsDistributor<E> {
190 pub fn new(apid_handler: Box<dyn SendableCcsdsPacketHandler<Error = E>>) -> Self {
191 CcsdsDistributor { apid_handler }
192 }
193
194 pub fn apid_handler_ref<T: SendableCcsdsPacketHandler<Error = E>>(&self) -> Option<&T> {
198 self.apid_handler.downcast_ref::<T>()
199 }
200
201 pub fn apid_handler_mut<T: SendableCcsdsPacketHandler<Error = E>>(&mut self) -> Option<&mut T> {
204 self.apid_handler.downcast_mut::<T>()
205 }
206
207 fn dispatch_ccsds(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) -> Result<(), CcsdsError<E>> {
208 let apid = sp_header.apid();
209 let valid_apids = self.apid_handler.valid_apids();
210 for &valid_apid in valid_apids {
211 if valid_apid == apid {
212 return self
213 .apid_handler
214 .handle_known_apid(sp_header, tc_raw)
215 .map_err(|e| CcsdsError::CustomError(e));
216 }
217 }
218 self.apid_handler
219 .handle_unknown_apid(sp_header, tc_raw)
220 .map_err(|e| CcsdsError::CustomError(e))
221 }
222}
223
224#[cfg(test)]
225pub(crate) mod tests {
226 use super::*;
227 use crate::tmtc::ccsds_distrib::{CcsdsDistributor, CcsdsPacketHandler};
228 use spacepackets::ecss::tc::PusTcCreator;
229 use spacepackets::ecss::WritablePusPacket;
230 use spacepackets::CcsdsPacket;
231 use std::collections::VecDeque;
232 use std::sync::{Arc, Mutex};
233 use std::vec::Vec;
234
235 fn is_send<T: Send>(_: &T) {}
236
237 pub fn generate_ping_tc(buf: &mut [u8]) -> &[u8] {
238 let mut sph = SpHeader::tc_unseg(0x002, 0x34, 0).unwrap();
239 let pus_tc = PusTcCreator::new_simple(&mut sph, 17, 1, None, true);
240 let size = pus_tc
241 .write_to_bytes(buf)
242 .expect("Error writing TC to buffer");
243 assert_eq!(size, 13);
244 &buf[0..size]
245 }
246
247 type SharedPacketQueue = Arc<Mutex<VecDeque<(u16, Vec<u8>)>>>;
248 pub struct BasicApidHandlerSharedQueue {
249 pub known_packet_queue: SharedPacketQueue,
250 pub unknown_packet_queue: SharedPacketQueue,
251 }
252
253 #[derive(Default)]
254 pub struct BasicApidHandlerOwnedQueue {
255 pub known_packet_queue: VecDeque<(u16, Vec<u8>)>,
256 pub unknown_packet_queue: VecDeque<(u16, Vec<u8>)>,
257 }
258
259 impl CcsdsPacketHandler for BasicApidHandlerSharedQueue {
260 type Error = ();
261 fn valid_apids(&self) -> &'static [u16] {
262 &[0x000, 0x002]
263 }
264
265 fn handle_known_apid(
266 &mut self,
267 sp_header: &SpHeader,
268 tc_raw: &[u8],
269 ) -> Result<(), Self::Error> {
270 let mut vec = Vec::new();
271 vec.extend_from_slice(tc_raw);
272 self.known_packet_queue
273 .lock()
274 .unwrap()
275 .push_back((sp_header.apid(), vec));
276 Ok(())
277 }
278
279 fn handle_unknown_apid(
280 &mut self,
281 sp_header: &SpHeader,
282 tc_raw: &[u8],
283 ) -> Result<(), Self::Error> {
284 let mut vec = Vec::new();
285 vec.extend_from_slice(tc_raw);
286 self.unknown_packet_queue
287 .lock()
288 .unwrap()
289 .push_back((sp_header.apid(), vec));
290 Ok(())
291 }
292 }
293
294 impl CcsdsPacketHandler for BasicApidHandlerOwnedQueue {
295 type Error = ();
296
297 fn valid_apids(&self) -> &'static [u16] {
298 &[0x000, 0x002]
299 }
300
301 fn handle_known_apid(
302 &mut self,
303 sp_header: &SpHeader,
304 tc_raw: &[u8],
305 ) -> Result<(), Self::Error> {
306 let mut vec = Vec::new();
307 vec.extend_from_slice(tc_raw);
308 Ok(self.known_packet_queue.push_back((sp_header.apid(), vec)))
309 }
310
311 fn handle_unknown_apid(
312 &mut self,
313 sp_header: &SpHeader,
314 tc_raw: &[u8],
315 ) -> Result<(), Self::Error> {
316 let mut vec = Vec::new();
317 vec.extend_from_slice(tc_raw);
318 Ok(self.unknown_packet_queue.push_back((sp_header.apid(), vec)))
319 }
320 }
321
322 #[test]
323 fn test_distribs_known_apid() {
324 let known_packet_queue = Arc::new(Mutex::default());
325 let unknown_packet_queue = Arc::new(Mutex::default());
326 let apid_handler = BasicApidHandlerSharedQueue {
327 known_packet_queue: known_packet_queue.clone(),
328 unknown_packet_queue: unknown_packet_queue.clone(),
329 };
330 let mut ccsds_distrib = CcsdsDistributor::new(Box::new(apid_handler));
331 is_send(&ccsds_distrib);
332 let mut test_buf: [u8; 32] = [0; 32];
333 let tc_slice = generate_ping_tc(test_buf.as_mut_slice());
334
335 ccsds_distrib.pass_tc(tc_slice).expect("Passing TC failed");
336 let recvd = known_packet_queue.lock().unwrap().pop_front();
337 assert!(unknown_packet_queue.lock().unwrap().is_empty());
338 assert!(recvd.is_some());
339 let (apid, packet) = recvd.unwrap();
340 assert_eq!(apid, 0x002);
341 assert_eq!(packet, tc_slice);
342 }
343
344 #[test]
345 fn test_distribs_unknown_apid() {
346 let known_packet_queue = Arc::new(Mutex::default());
347 let unknown_packet_queue = Arc::new(Mutex::default());
348 let apid_handler = BasicApidHandlerSharedQueue {
349 known_packet_queue: known_packet_queue.clone(),
350 unknown_packet_queue: unknown_packet_queue.clone(),
351 };
352 let mut ccsds_distrib = CcsdsDistributor::new(Box::new(apid_handler));
353 let mut sph = SpHeader::tc_unseg(0x004, 0x34, 0).unwrap();
354 let pus_tc = PusTcCreator::new_simple(&mut sph, 17, 1, None, true);
355 let mut test_buf: [u8; 32] = [0; 32];
356 pus_tc
357 .write_to_bytes(test_buf.as_mut_slice())
358 .expect("Error writing TC to buffer");
359 ccsds_distrib.pass_tc(&test_buf).expect("Passing TC failed");
360 let recvd = unknown_packet_queue.lock().unwrap().pop_front();
361 assert!(known_packet_queue.lock().unwrap().is_empty());
362 assert!(recvd.is_some());
363 let (apid, packet) = recvd.unwrap();
364 assert_eq!(apid, 0x004);
365 assert_eq!(packet.as_slice(), test_buf);
366 }
367}