rseip_eip/
encapsulation.rs

1// rseip
2//
3// rseip - Ethernet/IP (CIP) in pure Rust.
4// Copyright: 2021, Joylei <leingliu@gmail.com>
5// License: MIT
6
7use crate::consts::{ENCAPSULATION_DATA_MAX_LEN, ENCAPSULATION_HEADER_LEN};
8use bytes::Buf;
9use rseip_core::{
10    codec::{Decode, Encode, Encoder},
11    hex::AsHex,
12    Error,
13};
14
15/// UCMM: 504 bytes
16/// max: 65535
17#[derive(Debug, Default)]
18pub struct EncapsulationPacket<T> {
19    pub hdr: EncapsulationHeader,
20    /// max length: 65511
21    pub data: T,
22}
23
24/// header: 24 bytes
25#[derive(Debug, Default)]
26pub struct EncapsulationHeader {
27    pub command: u16,
28    /// Length, in bytes, of the data portion of the message
29    pub length: u16,
30    pub session_handle: u32,
31    pub status: u32,
32    pub sender_context: [u8; 8],
33    /// shall be 0, receiver should ignore the command if not zero
34    pub options: u32,
35}
36
37impl EncapsulationHeader {
38    #[inline]
39    pub fn ensure_command<E: Error>(&self, command_code: u16) -> Result<(), E> {
40        if self.command != command_code {
41            return Err(E::invalid_value(
42                format_args!("command code {:#0x?}", self.command),
43                command_code.as_hex(),
44            ));
45        }
46        Ok(())
47    }
48}
49
50impl<T: Encode> Encode for EncapsulationPacket<T> {
51    #[inline]
52    fn encode<A: Encoder>(
53        mut self,
54        buf: &mut bytes::BytesMut,
55        encoder: &mut A,
56    ) -> Result<(), A::Error>
57    where
58        Self: Sized,
59    {
60        let data_len = self.data.bytes_count();
61        debug_assert!(data_len <= ENCAPSULATION_DATA_MAX_LEN);
62
63        self.hdr.length = data_len as u16;
64        self.hdr.encode(buf, encoder)?;
65        self.data.encode(buf, encoder)?;
66        Ok(())
67    }
68
69    #[inline]
70    fn encode_by_ref<A: Encoder>(
71        &self,
72        buf: &mut bytes::BytesMut,
73        encoder: &mut A,
74    ) -> Result<(), A::Error> {
75        let data_len = self.data.bytes_count();
76        debug_assert!(data_len <= ENCAPSULATION_DATA_MAX_LEN);
77
78        //encode hdr
79        encoder.encode_u16(self.hdr.command, buf)?;
80        encoder.encode_u16(data_len as u16, buf)?;
81        encoder.encode_u32(self.hdr.session_handle, buf)?;
82        encoder.encode_u32(self.hdr.status, buf)?;
83        self.hdr.sender_context.encode_by_ref(buf, encoder)?;
84        encoder.encode_u32(self.hdr.options, buf)?;
85
86        //encode data
87        self.data.encode_by_ref(buf, encoder)?;
88        Ok(())
89    }
90
91    #[inline]
92    fn bytes_count(&self) -> usize {
93        ENCAPSULATION_HEADER_LEN + self.data.bytes_count()
94    }
95}
96
97impl Encode for EncapsulationHeader {
98    #[inline]
99    fn encode<A: Encoder>(self, buf: &mut bytes::BytesMut, encoder: &mut A) -> Result<(), A::Error>
100    where
101        Self: Sized,
102    {
103        encoder.encode_u16(self.command, buf)?;
104        encoder.encode_u16(self.length, buf)?;
105        encoder.encode_u32(self.session_handle, buf)?;
106        encoder.encode_u32(self.status, buf)?;
107        self.sender_context.encode_by_ref(buf, encoder)?;
108        encoder.encode_u32(self.options, buf)?;
109        Ok(())
110    }
111
112    #[inline]
113    fn encode_by_ref<A: Encoder>(
114        &self,
115        buf: &mut bytes::BytesMut,
116        encoder: &mut A,
117    ) -> Result<(), A::Error> {
118        encoder.encode_u16(self.command, buf)?;
119        encoder.encode_u16(self.length, buf)?;
120        encoder.encode_u32(self.session_handle, buf)?;
121        encoder.encode_u32(self.status, buf)?;
122        self.sender_context.encode_by_ref(buf, encoder)?;
123        encoder.encode_u32(self.options, buf)?;
124        Ok(())
125    }
126
127    #[inline(always)]
128    fn bytes_count(&self) -> usize {
129        ENCAPSULATION_HEADER_LEN
130    }
131}
132
133impl<'de> Decode<'de> for EncapsulationHeader {
134    #[inline]
135    fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
136    where
137        D: rseip_core::codec::Decoder<'de>,
138    {
139        decoder.ensure_size(ENCAPSULATION_HEADER_LEN)?;
140        let hdr = EncapsulationHeader {
141            command: decoder.decode_u16(),
142            length: decoder.decode_u16(),
143            session_handle: decoder.decode_u32(),
144            status: decoder.decode_u32(),
145            sender_context: {
146                let mut dst = [0; 8];
147                decoder.buf_mut().copy_to_slice(&mut dst);
148                dst
149            },
150            options: decoder.decode_u32(),
151        };
152
153        Ok(hdr)
154    }
155}