Skip to main content

simple_someip/e2e/
registry.rs

1//! E2E configuration registry for runtime E2E management.
2
3use std::collections::HashMap;
4
5use super::{E2ECheckStatus, E2EKey, E2EProfile, E2EState, Error, e2e_check, e2e_protect};
6
7/// Registry mapping message keys to E2E profile configurations and state.
8#[derive(Debug)]
9pub struct E2ERegistry {
10    map: HashMap<E2EKey, (E2EProfile, E2EState)>,
11}
12
13impl E2ERegistry {
14    /// Create an empty registry.
15    #[must_use]
16    pub fn new() -> Self {
17        Self {
18            map: HashMap::new(),
19        }
20    }
21
22    /// Register an E2E profile for the given key, creating fresh state.
23    pub fn register(&mut self, key: E2EKey, profile: E2EProfile) {
24        let state = E2EState::from_profile(&profile);
25        self.map.insert(key, (profile, state));
26    }
27
28    /// Remove E2E configuration for the given key.
29    pub fn unregister(&mut self, key: &E2EKey) {
30        self.map.remove(key);
31    }
32
33    /// Returns `true` if a profile is registered for `key`.
34    #[must_use]
35    pub fn contains_key(&self, key: &E2EKey) -> bool {
36        self.map.contains_key(key)
37    }
38
39    /// Run E2E check for `key` if configured.
40    ///
41    /// Returns `None` if no profile is registered for `key`.
42    /// Otherwise returns the check status and the best available payload
43    /// (stripped E2E header on success, original bytes on check failure).
44    pub fn check<'a>(
45        &mut self,
46        key: E2EKey,
47        payload: &'a [u8],
48        upper_header: [u8; 8],
49    ) -> Option<(E2ECheckStatus, &'a [u8])> {
50        let (profile, state) = self.map.get_mut(&key)?;
51        Some(e2e_check(profile, state, payload, upper_header))
52    }
53
54    /// Run E2E protect for `key` if configured.
55    ///
56    /// Returns `None` if no profile is registered for `key`.
57    pub fn protect(
58        &mut self,
59        key: E2EKey,
60        payload: &[u8],
61        upper_header: [u8; 8],
62        output: &mut [u8],
63    ) -> Option<Result<usize, Error>> {
64        let (profile, state) = self.map.get_mut(&key)?;
65        Some(e2e_protect(profile, state, payload, upper_header, output))
66    }
67}
68
69impl Default for E2ERegistry {
70    fn default() -> Self {
71        Self::new()
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78    use crate::e2e::{Profile4Config, Profile5Config};
79
80    fn make_key() -> E2EKey {
81        E2EKey::new(0x1234, 0x5678)
82    }
83
84    #[test]
85    fn register_and_check_profile4() {
86        let mut reg = E2ERegistry::new();
87        let key = make_key();
88        let config = Profile4Config::new(0x12345678, 15);
89        reg.register(key, E2EProfile::Profile4(config.clone()));
90        assert!(reg.contains_key(&key));
91
92        // Protect a payload
93        let payload = b"Hello";
94        let mut out = [0u8; 64];
95        let len = reg
96            .protect(key, payload, [0; 8], &mut out)
97            .unwrap()
98            .unwrap();
99
100        // Check it
101        let (status, stripped) = reg.check(key, &out[..len], [0; 8]).unwrap();
102        assert_eq!(status, E2ECheckStatus::Ok);
103        assert_eq!(stripped, payload);
104    }
105
106    #[test]
107    fn register_and_check_profile5() {
108        let mut reg = E2ERegistry::new();
109        let key = make_key();
110        let config = Profile5Config::new(0x1234, 20, 15);
111        reg.register(key, E2EProfile::Profile5(config));
112
113        let mut payload = [0u8; 20];
114        payload[..5].copy_from_slice(b"Hello");
115        let mut out = [0u8; 64];
116        let len = reg
117            .protect(key, &payload, [0; 8], &mut out)
118            .unwrap()
119            .unwrap();
120
121        let (status, stripped) = reg.check(key, &out[..len], [0; 8]).unwrap();
122        assert_eq!(status, E2ECheckStatus::Ok);
123        assert_eq!(stripped, &payload);
124    }
125
126    #[test]
127    fn unregistered_key_returns_none() {
128        let mut reg = E2ERegistry::new();
129        let key = make_key();
130        assert!(!reg.contains_key(&key));
131        assert!(reg.check(key, b"test", [0; 8]).is_none());
132        assert!(reg.protect(key, b"test", [0; 8], &mut [0; 64]).is_none());
133    }
134
135    #[test]
136    fn unregister_removes_key() {
137        let mut reg = E2ERegistry::new();
138        let key = make_key();
139        reg.register(key, E2EProfile::Profile4(Profile4Config::new(0, 15)));
140        assert!(reg.contains_key(&key));
141        reg.unregister(&key);
142        assert!(!reg.contains_key(&key));
143    }
144
145    #[test]
146    fn default_is_empty() {
147        let reg = E2ERegistry::default();
148        assert!(!reg.contains_key(&make_key()));
149    }
150}