a653rs_linux/
partition.rs

1use std::cmp::min;
2
3#[cfg(feature = "socket")]
4use std::{
5    fmt::Display,
6    io,
7    net::{TcpStream, UdpSocket},
8};
9
10use a653rs::prelude::{ApexErrorP4Ext, MAX_ERROR_MESSAGE_SIZE};
11use a653rs_linux_core::error::SystemError;
12use a653rs_linux_core::health_event::PartitionCall;
13use log::{set_logger, set_max_level, LevelFilter, Record, SetLoggerError};
14
15use crate::{CONSTANTS, SENDER};
16
17#[cfg(feature = "socket")]
18use crate::{TCP_SOCKETS, UDP_SOCKETS};
19
20/// Static functions for within a partition
21#[derive(Debug, Clone, Copy)]
22pub struct ApexLinuxPartition;
23
24impl ApexLinuxPartition {
25    pub fn get_partition_name() -> String {
26        CONSTANTS.name.clone()
27    }
28
29    #[cfg(feature = "socket")]
30    pub fn get_udp_socket(sockaddr: &str) -> Result<Option<UdpSocket>, ApexLinuxError> {
31        for stored in UDP_SOCKETS.iter() {
32            if stored.local_addr()?.to_string() == sockaddr {
33                let socket = stored.try_clone()?;
34                return Ok(Some(socket));
35            }
36        }
37        Ok(None)
38    }
39
40    #[cfg(feature = "socket")]
41    pub fn get_tcp_stream(sockaddr: &str) -> Result<Option<TcpStream>, ApexLinuxError> {
42        for stored in TCP_SOCKETS.iter() {
43            if stored.peer_addr()?.to_string() == sockaddr {
44                let socket = stored.try_clone()?;
45                return Ok(Some(socket));
46            }
47        }
48        Ok(None)
49    }
50
51    pub(crate) fn raise_system_error(error: SystemError) {
52        if let Err(e) = SENDER.try_send(&PartitionCall::Error(error)) {
53            panic!("Could not send SystemError event {error:?}. {e:?}")
54        };
55    }
56}
57
58#[cfg(feature = "socket")]
59#[derive(Debug, Clone)]
60pub enum ApexLinuxError {
61    SocketError,
62}
63
64#[cfg(feature = "socket")]
65impl Display for ApexLinuxError {
66    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67        match self {
68            ApexLinuxError::SocketError => f.write_str("Failed to get socket"),
69        }
70    }
71}
72
73#[cfg(feature = "socket")]
74impl From<io::Error> for ApexLinuxError {
75    fn from(_value: io::Error) -> Self {
76        ApexLinuxError::SocketError
77    }
78}
79
80static APEX_LOGGER: ApexLogger = ApexLogger();
81
82#[derive(Debug, Clone, Copy)]
83pub struct ApexLogger();
84
85impl ApexLogger {
86    pub fn install_logger(level: LevelFilter) -> Result<(), SetLoggerError> {
87        set_logger(&APEX_LOGGER).map(|()| set_max_level(level))
88    }
89
90    pub fn install_panic_hook() {
91        std::panic::set_hook(Box::new(|panic_info| error!("{panic_info:#?}")));
92    }
93}
94
95impl log::Log for ApexLogger {
96    fn enabled(&self, _meta: &log::Metadata) -> bool {
97        true
98    }
99
100    fn log(&self, record: &Record) {
101        let level = record.level() as usize;
102        for line in record.args().to_string().lines() {
103            let msg = if line.len() < MAX_ERROR_MESSAGE_SIZE {
104                format!("{level}{line}")
105            } else {
106                format!("{level}{}..", &line[..(MAX_ERROR_MESSAGE_SIZE - 3)])
107            };
108            let max = min(MAX_ERROR_MESSAGE_SIZE, msg.len());
109            ApexLinuxPartition::report_application_message(&msg.as_bytes()[0..max]).ok();
110        }
111    }
112
113    fn flush(&self) {}
114}