diff --git a/.idea/runConfigurations/Check.xml b/.idea/runConfigurations/Check.xml new file mode 100644 index 0000000..7742dee --- /dev/null +++ b/.idea/runConfigurations/Check.xml @@ -0,0 +1,18 @@ + + + + \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 1793871..303e398 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -211,6 +211,7 @@ version = "0.1.0" dependencies = [ "bus", "num", + "spacepackets", "thiserror", ] diff --git a/fsrc-core/Cargo.toml b/fsrc-core/Cargo.toml index c64545d..f12146b 100644 --- a/fsrc-core/Cargo.toml +++ b/fsrc-core/Cargo.toml @@ -9,3 +9,8 @@ edition = "2021" thiserror = "1.0" bus = "2.2.3" num = "0.4" +spacepackets = { path = "../spacepackets"} + +[features] +default = ["use_std"] +use_std = [] diff --git a/fsrc-core/examples/tc_server.rs b/fsrc-core/examples/tc_server.rs new file mode 100644 index 0000000..dfdced9 --- /dev/null +++ b/fsrc-core/examples/tc_server.rs @@ -0,0 +1,23 @@ +extern crate core; + +use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket}; +use std::thread; + +fn main() { + let server_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 7301); + let socket = UdpSocket::bind(&server_addr.clone()).expect("Error opening UDP socket"); + let mut recv_buf = [0; 1024]; + let jh = thread::spawn(move || { + let dummy_data = [1, 2, 3, 4]; + let client = UdpSocket::bind("127.0.0.1:7300").expect("Connecting to UDP server failed"); + client + .send_to(&dummy_data, &server_addr) + .expect(&*format!("Sending to {:?} failed", server_addr)); + }); + let (num_bytes, src) = socket.recv_from(&mut recv_buf).expect("UDP Receive error"); + println!( + "Received {num_bytes} bytes from {src}: {:x?}", + &recv_buf[0..num_bytes] + ); + jh.join().expect("Joining thread failed"); +} diff --git a/fsrc-core/examples/test.rs b/fsrc-core/examples/test.rs new file mode 100644 index 0000000..49a7405 --- /dev/null +++ b/fsrc-core/examples/test.rs @@ -0,0 +1,67 @@ +use postcard::{from_bytes, to_stdvec}; +use serde::{Deserialize, Serialize}; +use zerocopy::byteorder::{I32, U16}; +use zerocopy::{AsBytes, FromBytes, NetworkEndian, Unaligned}; + +#[derive(AsBytes, FromBytes, Unaligned, Debug, Eq, PartialEq)] +#[repr(C, packed)] +struct ZeroCopyTest { + some_bool: u8, + some_u16: U16, + some_i32: I32, + some_float: [u8; 4], +} + +#[derive(Serialize, Deserialize, Debug, PartialEq)] +struct PostcardTest { + some_bool: u8, + some_u16: u16, + some_i32: i32, + some_float: f32, +} + +#[derive(Serialize, Deserialize, Debug, PartialEq)] +struct SliceSerTest<'slice> { + some_u8: u8, + some_u32: u32, + some_slice: &'slice [u8], +} + +fn main() { + let pc_test = PostcardTest { + some_bool: true as u8, + some_u16: 0x42, + some_i32: -200, + some_float: 7.7_f32, + }; + + let out = to_stdvec(&pc_test).unwrap(); + println!("{:#04x?}", out); + + let sample_hk = ZeroCopyTest { + some_bool: true as u8, + some_u16: U16::from(0x42), + some_i32: I32::from(-200), + some_float: 7.7_f32.to_be_bytes(), + }; + let mut slice = [0; 11]; + sample_hk.write_to(slice.as_mut_slice()); + println!("{:#04x?}", slice); + + let ser_vec; + { + let test_buf = [0, 1, 2, 3]; + let test_with_slice = SliceSerTest { + some_u8: 12, + some_u32: 1, + some_slice: test_buf.as_slice(), + }; + ser_vec = to_stdvec(&test_with_slice).unwrap(); + println!("{:#04x?}", out); + } + + { + let test_deser: SliceSerTest = from_bytes(ser_vec.as_slice()).unwrap(); + println!("{:?}", test_deser); + } +} diff --git a/fsrc-core/src/hal/host/mod.rs b/fsrc-core/src/hal/host/mod.rs new file mode 100644 index 0000000..d9e7799 --- /dev/null +++ b/fsrc-core/src/hal/host/mod.rs @@ -0,0 +1 @@ +pub mod udp_server; diff --git a/fsrc-core/src/hal/host/udp_server.rs b/fsrc-core/src/hal/host/udp_server.rs new file mode 100644 index 0000000..d4cb29f --- /dev/null +++ b/fsrc-core/src/hal/host/udp_server.rs @@ -0,0 +1,29 @@ +use crate::tmtc::ReceivesTc; +use std::net::{SocketAddr, ToSocketAddrs, UdpSocket}; +use std::vec::Vec; + +pub struct UdpTmtcServer { + socket: UdpSocket, + recv_buf: Vec, + tc_receiver: Box, +} + +impl UdpTmtcServer { + pub fn new( + addr: A, + max_recv_size: usize, + tc_receiver: Box, + ) -> Result { + Ok(Self { + socket: UdpSocket::bind(addr)?, + recv_buf: Vec::with_capacity(max_recv_size), + tc_receiver, + }) + } + + pub fn recv_tc(&mut self) -> Result<(usize, SocketAddr), std::io::Error> { + let res = self.socket.recv_from(&mut self.recv_buf)?; + self.tc_receiver.pass_tc(&self.recv_buf[0..res.0]); + Ok(res) + } +} diff --git a/fsrc-core/src/hal/mod.rs b/fsrc-core/src/hal/mod.rs new file mode 100644 index 0000000..43769ba --- /dev/null +++ b/fsrc-core/src/hal/mod.rs @@ -0,0 +1,2 @@ +#[cfg(feature = "use_std")] +pub mod host; diff --git a/fsrc-core/src/lib.rs b/fsrc-core/src/lib.rs index 148ac45..5b4c86b 100644 --- a/fsrc-core/src/lib.rs +++ b/fsrc-core/src/lib.rs @@ -2,5 +2,7 @@ pub mod event_man; pub mod events; pub mod executable; +pub mod hal; pub mod objects; pub mod pool; +pub mod tmtc; diff --git a/fsrc-core/src/pool.rs b/fsrc-core/src/pool.rs index 99f8853..da53bd0 100644 --- a/fsrc-core/src/pool.rs +++ b/fsrc-core/src/pool.rs @@ -171,7 +171,7 @@ impl LocalPool { /// Add new data to the pool. It will attempt to reserve a memory block with the appropriate /// size and then copy the given data to the block. Yields a [StoreAddr] which can be used /// to access the data stored in the pool - pub fn add(&mut self, data: impl AsRef<[u8]>) -> Result { + pub fn add(&mut self, data: &[u8]) -> Result { let data_len = data.as_ref().len(); if data_len > Self::MAX_SIZE { return Err(StoreError::DataTooLarge(data_len)); diff --git a/fsrc-core/src/tmtc/ccsds_distrib.rs b/fsrc-core/src/tmtc/ccsds_distrib.rs new file mode 100644 index 0000000..dafadac --- /dev/null +++ b/fsrc-core/src/tmtc/ccsds_distrib.rs @@ -0,0 +1,19 @@ +use crate::tmtc::{ReceivesCcsds, ReceivesTc}; +use spacepackets::{CcsdsPacket, SpHeader}; + +pub trait ApidHandler { + fn get_apid_handler(&self, apid: u16) -> Box; +} + +struct CcsdsDistributor { + apid_handlers: Box, +} + +impl ReceivesTc for CcsdsDistributor { + fn pass_tc(&mut self, tm_raw: &[u8]) { + // TODO: Better error handling + let sp_header = SpHeader::from_raw_slice(tm_raw).unwrap(); + let mut handler = self.apid_handlers.get_apid_handler(sp_header.apid()); + handler.pass_ccsds(&sp_header, tm_raw).unwrap(); + } +} diff --git a/fsrc-core/src/tmtc/mod.rs b/fsrc-core/src/tmtc/mod.rs new file mode 100644 index 0000000..2bf8cce --- /dev/null +++ b/fsrc-core/src/tmtc/mod.rs @@ -0,0 +1,18 @@ +use spacepackets::ecss::PusError; +use spacepackets::tc::PusTc; +use spacepackets::{PacketError, SpHeader}; + +pub mod ccsds_distrib; +pub mod pus_distrib; + +pub trait ReceivesTc { + fn pass_tc(&mut self, tc_raw: &[u8]); +} + +pub trait ReceivesCcsds { + fn pass_ccsds(&mut self, header: &SpHeader, tm_raw: &[u8]) -> Result<(), PacketError>; +} + +pub trait ReceivesPus { + fn pass_pus(&mut self, pus_tc: &PusTc) -> Result<(), PusError>; +} diff --git a/fsrc-core/src/tmtc/pus_distrib.rs b/fsrc-core/src/tmtc/pus_distrib.rs new file mode 100644 index 0000000..f9dccd4 --- /dev/null +++ b/fsrc-core/src/tmtc/pus_distrib.rs @@ -0,0 +1,39 @@ +use crate::tmtc::{ReceivesCcsds, ReceivesPus, ReceivesTc}; +use spacepackets::ecss::PusPacket; +use spacepackets::tc::PusTc; +use spacepackets::{CcsdsPacket, PacketError, SpHeader}; + +pub trait PusServiceProvider { + fn get_apid(&self, service: u8) -> u16; + fn get_service_handler(&self, service: u8, subservice: u8) -> Box; +} + +pub struct PusDistributor { + service_provider: Box, +} + +impl ReceivesTc for PusDistributor { + fn pass_tc(&mut self, tm_raw: &[u8]) { + // Convert to ccsds and call pass_ccsds + let sp_header = SpHeader::from_raw_slice(tm_raw).unwrap(); + self.pass_ccsds(&sp_header, tm_raw).unwrap(); + } +} + +impl ReceivesCcsds for PusDistributor { + fn pass_ccsds(&mut self, _header: &SpHeader, tm_raw: &[u8]) -> Result<(), PacketError> { + // TODO: Better error handling + let (tc, _) = PusTc::new_from_raw_slice(tm_raw).unwrap(); + + let mut srv_provider = self + .service_provider + .get_service_handler(tc.service(), tc.subservice()); + let apid = self.service_provider.get_apid(tc.service()); + if apid != tc.apid() { + // TODO: Dedicated error + return Ok(()); + } + srv_provider.pass_pus(&tc).unwrap(); + Ok(()) + } +} diff --git a/spacepackets b/spacepackets index 063b849..a7b97e2 160000 --- a/spacepackets +++ b/spacepackets @@ -1 +1 @@ -Subproject commit 063b8491545a71dee0ada2a15dc565f9cced75d2 +Subproject commit a7b97e22f5c7a183372bd30933e66b8bf3fc6a7b