ipmi_rs/connection/impls/rmcp/v2_0/messages/
rakp_4.rs1use 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 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}