ipmi_rs/connection/impls/rmcp/v2_0/messages/
rakp_4.rs

1use std::num::NonZeroU32;
2
3use super::RakpErrorStatusCode;
4
5#[derive(Debug, Clone, Copy, PartialEq)]
6pub enum ParseError {
7    NotEnoughData,
8    ErrorStatusCode(ErrorStatusCode),
9    UnknownErrorStatusCode(u8),
10    ZeroManagedSystemSessionId,
11}
12
13#[derive(Debug, Clone)]
14pub struct RakpMessage4<'a> {
15    pub message_tag: u8,
16    pub managed_system_session_id: NonZeroU32,
17    pub integrity_check_value: &'a [u8],
18}
19
20impl<'a> RakpMessage4<'a> {
21    pub fn from_data(data: &'a [u8]) -> Result<Self, ParseError> {
22        // 4 = tag, status code, reserved bytes
23        if data.len() < 4 {
24            return Err(ParseError::NotEnoughData);
25        }
26
27        let message_tag = data[0];
28        let status_code = data[1];
29
30        if status_code != 0 {
31            return Err(ErrorStatusCode::try_from(status_code)
32                .map(ParseError::ErrorStatusCode)
33                .unwrap_or(ParseError::UnknownErrorStatusCode(status_code)));
34        }
35
36        if data.len() < 8 {
37            return Err(ParseError::NotEnoughData);
38        }
39
40        let managed_system_session_id =
41            if let Ok(v) = u32::from_le_bytes(data[4..8].try_into().unwrap()).try_into() {
42                v
43            } else {
44                return Err(ParseError::ZeroManagedSystemSessionId);
45            };
46        let integrity_check_value = &data[8..];
47
48        Ok(Self {
49            message_tag,
50            managed_system_session_id,
51            integrity_check_value,
52        })
53    }
54}
55
56#[derive(Debug, Clone, Copy, PartialEq)]
57#[repr(u8)]
58pub enum ErrorStatusCode {
59    Common(RakpErrorStatusCode),
60    InactiveSessionId = 0x08,
61    InvalidIntegrityCheckValue = 0x0F,
62}
63
64impl TryFrom<u8> for ErrorStatusCode {
65    type Error = ();
66
67    fn try_from(value: u8) -> Result<Self, Self::Error> {
68        if let Ok(common) = RakpErrorStatusCode::try_from(value) {
69            Ok(Self::Common(common))
70        } else if value == 0x08 {
71            Ok(Self::InactiveSessionId)
72        } else if value == 0x0F {
73            Ok(Self::InvalidIntegrityCheckValue)
74        } else {
75            Err(())
76        }
77    }
78}