1#![deny(dead_code)]
7
8#[macro_use]
9extern crate log;
10
11#[cfg(feature = "socket")]
12use std::net::{TcpStream, UdpSocket};
13#[cfg(feature = "socket")]
14use std::os::fd::FromRawFd;
15
16#[cfg(feature = "socket")]
17use a653rs_linux_core::ipc::IoReceiver;
18
19use std::os::fd::{AsRawFd, OwnedFd};
20use std::sync::Arc;
21use std::time::{Duration, Instant};
22
23use a653rs::prelude::OperatingMode;
24use a653rs_linux_core::file::{get_memfd, TempFile};
25use a653rs_linux_core::health_event::PartitionCall;
26use a653rs_linux_core::ipc::{self, IpcSender};
27use a653rs_linux_core::partition::*;
28use a653rs_linux_core::syscall::SYSCALL_SOCKET_PATH;
29use nix::sys::socket::{self, connect, AddressFamily, SockFlag, SockType, UnixAddr};
30use once_cell::sync::{Lazy, OnceCell};
31use process::Process;
32use tinyvec::ArrayVec;
33
34pub mod apex;
35pub mod partition;
36pub mod syscall;
37pub(crate) mod process;
39
40const SAMPLING_PORTS_FILE: &str = "sampling_channels";
41const QUEUING_PORTS_FILE: &str = "queuing_channels";
43
44pub(crate) static CONSTANTS: Lazy<PartitionConstants> =
45 Lazy::new(|| PartitionConstants::open().unwrap());
46
47pub(crate) static SYSTEM_TIME: Lazy<Instant> = Lazy::new(|| {
48 TempFile::<Instant>::try_from(CONSTANTS.start_time_fd)
49 .unwrap()
50 .read()
51 .unwrap()
52});
53
54pub(crate) static PARTITION_MODE: Lazy<TempFile<OperatingMode>> =
55 Lazy::new(|| TempFile::<OperatingMode>::try_from(CONSTANTS.partition_mode_fd).unwrap());
56
57pub(crate) static PERIODIC_PROCESS: OnceCell<Arc<Process>> = OnceCell::new();
58pub(crate) static APERIODIC_PROCESS: OnceCell<Arc<Process>> = OnceCell::new();
59
60pub(crate) type SamplingPortsType = (usize, Duration);
61pub(crate) static SAMPLING_PORTS: Lazy<TempFile<ArrayVec<[SamplingPortsType; 32]>>> =
62 Lazy::new(|| {
63 if let Ok(fd) = get_memfd(SAMPLING_PORTS_FILE) {
64 TempFile::try_from(fd).unwrap()
65 } else {
66 let file = TempFile::create(SAMPLING_PORTS_FILE).unwrap();
67 file.write(&Default::default()).unwrap();
68 file
69 }
70 });
71
72pub(crate) type QueuingPortsType = usize;
73pub(crate) static QUEUING_PORTS: Lazy<TempFile<ArrayVec<[QueuingPortsType; 32]>>> =
74 Lazy::new(|| {
75 if let Ok(fd) = get_memfd(QUEUING_PORTS_FILE) {
76 TempFile::try_from(fd).unwrap()
77 } else {
78 let file = TempFile::create(QUEUING_PORTS_FILE).unwrap();
79 file.write(&Default::default()).unwrap();
80 file
81 }
82 });
83
84pub(crate) static SENDER: Lazy<IpcSender<PartitionCall>> =
85 Lazy::new(|| ipc::connect_sender(PartitionConstants::IPC_SENDER.as_ref()).unwrap());
86
87#[cfg(feature = "socket")]
88pub(crate) static UDP_IO_RX: Lazy<IoReceiver<UdpSocket>> =
89 Lazy::new(|| unsafe { IoReceiver::<UdpSocket>::from_raw_fd(CONSTANTS.udp_io_fd) });
90
91#[cfg(feature = "socket")]
92pub(crate) static TCP_IO_RX: Lazy<IoReceiver<TcpStream>> =
93 Lazy::new(|| unsafe { IoReceiver::<TcpStream>::from_raw_fd(CONSTANTS.tcp_io_fd) });
94
95pub(crate) static SYSCALL: Lazy<OwnedFd> = Lazy::new(|| {
96 let syscall_socket = socket::socket(
97 AddressFamily::Unix,
98 SockType::Datagram,
99 SockFlag::empty(),
100 None,
101 )
102 .unwrap();
103
104 connect(
105 syscall_socket.as_raw_fd(),
106 &UnixAddr::new(SYSCALL_SOCKET_PATH).unwrap(),
107 )
108 .unwrap();
109
110 syscall_socket
111});
112
113#[cfg(feature = "socket")]
114pub(crate) static UDP_SOCKETS: Lazy<Vec<UdpSocket>> = Lazy::new(|| receive_sockets(&UDP_IO_RX));
115
116#[cfg(feature = "socket")]
117pub(crate) static TCP_SOCKETS: Lazy<Vec<TcpStream>> = Lazy::new(|| receive_sockets(&TCP_IO_RX));
118
119#[cfg(feature = "socket")]
123fn receive_sockets<T: FromRawFd>(receiver: &IoReceiver<T>) -> Vec<T> {
124 let mut sockets: Vec<T> = Vec::default();
125 loop {
126 match unsafe { receiver.try_receive() } {
127 Ok(i) => {
128 if let Some(i) = i {
129 sockets.push(i);
130 } else {
131 return sockets;
132 }
133 }
134 Err(e) => panic!("Could not receive sockets from hypervisor: {e:?}"),
135 }
136 }
137}