pn_dcp/packet/
mod.rs

1pub mod extend_trait;
2pub mod get_req;
3pub mod get_resp;
4pub mod ident_req;
5pub mod ident_resp;
6pub mod set_req;
7pub mod set_resp;
8
9use crate::comm::BytesWrap;
10use crate::comm::PROFINET_ETHER_TYPE;
11use anyhow::{bail, Result};
12use pnet::util::MacAddr;
13
14#[derive(Debug, Copy, Clone, Eq, PartialEq)]
15pub enum PnDcpTy {
16    HelloReq,       // 0xfe, 0xfc, 0x06, 0x00
17    HelloRespSuc,   // 0xfe, 0xfc, 0x06, 0x01
18    HelloRespUnsup, // 0xfe, 0xfc, 0x06, 0x05
19    IdentReq,       // 0xfe, 0xfe, 0x05, 0x00
20    IdentRespSuc,   // 0xfe, 0xff, 0x05, 0x01
21    // IdentRespUnsup, // 0xfe, 0xff, 0x05, 0x05
22    GetReq,       // 0xfe, 0xfd, 0x03, 0x00
23    GetRespSuc,   // 0xfe, 0xfd, 0x03, 0x01
24    GetRespUnsup, // 0xfe, 0xfd, 0x03, 0x05
25    SetReq,       // 0xfe, 0xfd, 0x04, 0x00
26    SetRespSuc,   // 0xfe, 0xfd, 0x04, 0x01
27    SetRespUnsup, // 0xfe, 0xfd, 0x04, 0x05
28}
29impl PnDcpTy {
30    pub fn to_u8_array(&self) -> [u8; 4] {
31        match self {
32            Self::HelloReq => [0xfe, 0xfc, 0x06, 0x00],
33            Self::HelloRespSuc => [0xfe, 0xfc, 0x06, 0x01],
34            Self::HelloRespUnsup => [0xfe, 0xfc, 0x06, 0x05],
35            Self::IdentReq => [0xfe, 0xfe, 0x05, 0x00],
36            Self::IdentRespSuc => [0xfe, 0xff, 0x05, 0x01],
37            // Self::IdentRespUnsup => [0xfe, 0xff, 0x05, 0x05],
38            Self::GetReq => [0xfe, 0xfd, 0x03, 0x00],
39            Self::GetRespSuc => [0xfe, 0xfd, 0x03, 0x01],
40            Self::GetRespUnsup => [0xfe, 0xfd, 0x03, 0x05],
41            Self::SetReq => [0xfe, 0xfd, 0x04, 0x00],
42            Self::SetRespSuc => [0xfe, 0xfd, 0x04, 0x01],
43            Self::SetRespUnsup => [0xfe, 0xfd, 0x04, 0x05],
44        }
45    }
46}
47impl TryFrom<[u8; 4]> for PnDcpTy {
48    type Error = anyhow::Error;
49    fn try_from(value: [u8; 4]) -> std::result::Result<Self, Self::Error> {
50        match value {
51            [0xfe, 0xfc, 0x06, 0x00] => Ok(Self::HelloReq),
52            [0xfe, 0xfc, 0x06, 0x01] => Ok(Self::HelloRespSuc),
53            [0xfe, 0xfc, 0x06, 0x05] => Ok(Self::HelloRespUnsup),
54            [0xfe, 0xfe, 0x05, 0x00] => Ok(Self::IdentReq),
55            [0xfe, 0xff, 0x05, 0x01] => Ok(Self::IdentRespSuc),
56            // [0xfe, 0xff, 0x05, 0x05] => Ok(Self::IdentRespUnsup),
57            [0xfe, 0xfd, 0x03, 0x00] => Ok(Self::GetReq),
58            [0xfe, 0xfd, 0x03, 0x01] => Ok(Self::GetRespSuc),
59            [0xfe, 0xfd, 0x03, 0x05] => Ok(Self::GetRespUnsup),
60            [0xfe, 0xfd, 0x04, 0x00] => Ok(Self::SetReq),
61            [0xfe, 0xfd, 0x04, 0x01] => Ok(Self::SetRespSuc),
62            [0xfe, 0xfd, 0x04, 0x05] => Ok(Self::SetRespUnsup),
63            _ => bail!("not a pn-dcp type!"),
64        }
65    }
66}
67pub struct PnDcp {
68    pub head: DcpHead,
69    pub blocks: BytesWrap,
70}
71
72impl TryFrom<&[u8]> for PnDcp {
73    type Error = anyhow::Error;
74
75    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
76        let head = DcpHead::try_from(value)?;
77        if let Some(blocks_data) = value.get(26..(26 + head.payload_len)) {
78            let blocks: BytesWrap = blocks_data.to_vec().into();
79            return Ok(Self { head, blocks });
80        }
81        bail!("长度不足,非PnDcg包");
82    }
83}
84
85#[derive(Debug, Eq, PartialEq, Clone)]
86pub struct DcpHead {
87    pub destination: MacAddr,
88    pub source: MacAddr,
89    pub ty: PnDcpTy,
90    pub xid: [u8; 4],
91    pub reserved_or_delay: [u8; 2],
92    pub payload_len: usize,
93}
94
95impl DcpHead {
96    pub fn append_data(&self, data: &mut Vec<u8>) {
97        data.extend_from_slice(self.destination.octets().as_slice());
98        data.extend_from_slice(self.source.octets().as_slice());
99        data.extend_from_slice(PROFINET_ETHER_TYPE.0.to_be_bytes().as_slice());
100        data.extend_from_slice(self.ty.to_u8_array().as_slice());
101        data.extend_from_slice(self.xid.as_slice());
102        data.extend_from_slice(self.reserved_or_delay.as_slice());
103        data.extend_from_slice((self.payload_len as u16).to_be_bytes().as_slice());
104    }
105    pub fn new(destination: MacAddr, source: MacAddr, ty: PnDcpTy) -> Self {
106        Self {
107            destination,
108            source,
109            ty,
110            xid: [0u8; 4],
111            reserved_or_delay: [0u8; 2],
112            payload_len: 0,
113        }
114    }
115    pub fn set_xid(&mut self, xid: [u8; 4]) {
116        self.xid = xid;
117    }
118    pub fn set_reserved_or_delay(&mut self, reserved_or_delay: [u8; 2]) {
119        self.reserved_or_delay = reserved_or_delay;
120    }
121    // pub fn set_payload_len(&mut self, payload_len: usize) {
122    //     self.payload_len = payload_len;
123    // }
124    pub fn add_payload_len(&mut self, add: usize) {
125        self.payload_len += add;
126    }
127}
128
129impl TryFrom<&[u8]> for DcpHead {
130    type Error = anyhow::Error;
131
132    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
133        if let Some(payload_len) = value
134            .get(25)
135            .and_then(|x| Some(u16::from_be_bytes([value[24], *x]) as usize))
136        {
137            if PROFINET_ETHER_TYPE.0 != u16::from_be_bytes([value[12], value[13]]) {
138                bail!("the packet is not a pn-dcp!");
139
140            }
141            let ty = PnDcpTy::try_from([value[14], value[15], value[16], value[17]])?;
142            if payload_len + 26 > value.len() {
143                bail!("payload({}) + 26 > {}", payload_len, value.len());
144            }
145            let destination =
146                MacAddr::new(value[0], value[1], value[2], value[3], value[4], value[5]);
147            let source = MacAddr::new(value[6], value[7], value[8], value[9], value[10], value[11]);
148            let xid: [u8; 4] = [value[18], value[19], value[20], value[21]];
149            let reserved_or_delay: [u8; 2] = [value[22], value[23]];
150            return Ok(DcpHead {
151                destination,
152                source,
153                ty,
154                xid,
155                reserved_or_delay,
156                payload_len,
157            });
158        }
159        bail!("长度不足,非PnDcg包");
160    }
161}
162
163pub enum FrameId {
164    Hello,
165    GetOrSet,
166    IdentReq,
167    IdentResp,
168    UnSupport(u8, u8),
169}
170impl From<[u8; 2]> for FrameId {
171    fn from(a: [u8; 2]) -> Self {
172        match a {
173            [0xfe, 0xfc] => Self::Hello,
174            [0xfe, 0xfd] => Self::GetOrSet,
175            [0xfe, 0xfe] => Self::IdentReq,
176            [0xfe, 0xff] => Self::IdentResp,
177            [a, b] => Self::UnSupport(a, b),
178        }
179    }
180}