rseip_eip/codec/
command.rs

1// rseip
2//
3// rseip - Ethernet/IP (CIP) in pure Rust.
4// Copyright: 2021, Joylei <leingliu@gmail.com>
5// License: MIT
6
7use super::*;
8use crate::{command::*, consts::*, EncapsulationPacket, Error};
9use bytes::{BufMut, BytesMut};
10use tokio_util::codec::Encoder;
11
12impl<C: Command, E: Error> Encoder<C> for ClientCodec<E> {
13    type Error = E;
14    #[inline(always)]
15    fn encode(&mut self, item: C, dst: &mut BytesMut) -> Result<(), Self::Error> {
16        item.encode(dst, self)
17    }
18}
19
20impl<D: Encode> Encode for command::Nop<D> {
21    #[inline]
22    fn encode<A: codec::Encoder>(
23        self,
24        dst: &mut BytesMut,
25        encoder: &mut A,
26    ) -> Result<(), A::Error> {
27        // reserve space for performance
28        dst.reserve(self.bytes_count());
29
30        let mut pkt = EncapsulationPacket {
31            hdr: Default::default(),
32            data: self.data,
33        };
34        pkt.hdr.command = Self::command_code();
35        pkt.encode(dst, encoder)
36    }
37
38    #[inline]
39    fn encode_by_ref<A: codec::Encoder>(
40        &self,
41        buf: &mut BytesMut,
42        encoder: &mut A,
43    ) -> Result<(), A::Error> {
44        // reserve space for performance
45        buf.reserve(self.bytes_count());
46
47        let mut pkt = EncapsulationPacket {
48            hdr: Default::default(),
49            data: &self.data,
50        };
51        pkt.hdr.command = Self::command_code();
52        pkt.encode(buf, encoder)
53    }
54
55    #[inline]
56    fn bytes_count(&self) -> usize {
57        ENCAPSULATION_HEADER_LEN + self.data.bytes_count()
58    }
59}
60
61impl Encode for ListIdentity {
62    #[inline]
63    fn encode_by_ref<A: codec::Encoder>(
64        &self,
65        buf: &mut BytesMut,
66        encoder: &mut A,
67    ) -> Result<(), A::Error> {
68        let mut pkt = EncapsulationPacket::default();
69        pkt.hdr.command = Self::command_code();
70        pkt.data = ();
71        pkt.encode(buf, encoder)
72    }
73
74    #[inline(always)]
75    fn bytes_count(&self) -> usize {
76        ENCAPSULATION_HEADER_LEN
77    }
78}
79
80impl Encode for ListInterfaces {
81    #[inline]
82    fn encode_by_ref<A: codec::Encoder>(
83        &self,
84        buf: &mut BytesMut,
85        encoder: &mut A,
86    ) -> Result<(), A::Error> {
87        let mut pkt = EncapsulationPacket::default();
88        pkt.hdr.command = Self::command_code();
89        pkt.data = ();
90        pkt.encode(buf, encoder)
91    }
92
93    #[inline(always)]
94    fn bytes_count(&self) -> usize {
95        ENCAPSULATION_HEADER_LEN
96    }
97}
98
99impl Encode for ListServices {
100    #[inline]
101    fn encode_by_ref<A: codec::Encoder>(
102        &self,
103        buf: &mut BytesMut,
104        encoder: &mut A,
105    ) -> Result<(), A::Error> {
106        let mut pkt = EncapsulationPacket::default();
107        pkt.hdr.command = Self::command_code();
108        pkt.data = ();
109        pkt.encode(buf, encoder)
110    }
111    #[inline(always)]
112    fn bytes_count(&self) -> usize {
113        ENCAPSULATION_HEADER_LEN
114    }
115}
116
117impl Encode for RegisterSession {
118    #[inline]
119    fn encode_by_ref<A: codec::Encoder>(
120        &self,
121        buf: &mut BytesMut,
122        encoder: &mut A,
123    ) -> Result<(), A::Error> {
124        let mut pkt: EncapsulationPacket<&[u8]> = EncapsulationPacket::default();
125        pkt.hdr.command = Self::command_code();
126        pkt.data = &[0x01, 0x00, 0x00, 0x00];
127        pkt.encode(buf, encoder)
128    }
129
130    #[inline(always)]
131    fn bytes_count(&self) -> usize {
132        ENCAPSULATION_HEADER_LEN + 4
133    }
134}
135
136impl Encode for UnRegisterSession {
137    #[inline]
138    fn encode_by_ref<A: codec::Encoder>(
139        &self,
140        buf: &mut BytesMut,
141        encoder: &mut A,
142    ) -> Result<(), A::Error> {
143        let mut pkt = EncapsulationPacket::default();
144        pkt.hdr.command = Self::command_code();
145        pkt.hdr.session_handle = self.session_handle;
146        pkt.data = ();
147        pkt.encode(buf, encoder)
148    }
149    #[inline(always)]
150    fn bytes_count(&self) -> usize {
151        ENCAPSULATION_HEADER_LEN
152    }
153}
154
155impl<D: Encode> Encode for SendRRData<D> {
156    #[inline]
157    fn encode<A: codec::Encoder>(
158        self,
159        buf: &mut BytesMut,
160        encoder: &mut A,
161    ) -> Result<(), A::Error> {
162        let mut pkt = EncapsulationPacket {
163            hdr: Default::default(),
164            data: UnconnectedData {
165                timeout: self.timeout,
166                data: self.data,
167            },
168        };
169        pkt.hdr.command = Self::command_code();
170        pkt.hdr.session_handle = self.session_handle;
171        pkt.encode(buf, encoder)
172    }
173
174    #[inline]
175    fn encode_by_ref<A: codec::Encoder>(
176        &self,
177        buf: &mut BytesMut,
178        encoder: &mut A,
179    ) -> Result<(), A::Error> {
180        let mut pkt = EncapsulationPacket {
181            hdr: Default::default(),
182            data: UnconnectedData {
183                timeout: self.timeout,
184                data: &self.data,
185            },
186        };
187        pkt.hdr.command = Self::command_code();
188        pkt.hdr.session_handle = self.session_handle;
189        pkt.encode(buf, encoder)
190    }
191
192    #[inline]
193    fn bytes_count(&self) -> usize {
194        ENCAPSULATION_HEADER_LEN + 16 + self.data.bytes_count()
195    }
196}
197
198impl<D: Encode> Encode for SendUnitData<D> {
199    #[inline]
200    fn encode<A: codec::Encoder>(
201        self,
202        buf: &mut BytesMut,
203        encoder: &mut A,
204    ) -> Result<(), A::Error> {
205        let packed_data = ConnectedData {
206            connection_id: self.connection_id,
207            sequence_number: self.sequence_number,
208            data: self.data,
209        };
210        let mut pkt = EncapsulationPacket {
211            hdr: Default::default(),
212            data: packed_data,
213        };
214        pkt.hdr.command = Self::command_code();
215        pkt.hdr.session_handle = self.session_handle;
216        pkt.encode(buf, encoder)
217    }
218
219    #[inline]
220    fn encode_by_ref<A: codec::Encoder>(
221        &self,
222        buf: &mut BytesMut,
223        encoder: &mut A,
224    ) -> Result<(), A::Error> {
225        let packed_data = ConnectedData {
226            connection_id: self.connection_id,
227            sequence_number: self.sequence_number,
228            data: &self.data,
229        };
230        let mut pkt = EncapsulationPacket {
231            hdr: Default::default(),
232            data: packed_data,
233        };
234        pkt.hdr.command = Self::command_code();
235        pkt.hdr.session_handle = self.session_handle;
236        pkt.encode(buf, encoder)
237    }
238
239    #[inline]
240    fn bytes_count(&self) -> usize {
241        ENCAPSULATION_HEADER_LEN + 22 + self.data.bytes_count()
242    }
243}
244
245struct UnconnectedData<D> {
246    timeout: u16,
247    data: D,
248}
249
250impl<D: Encode> UnconnectedData<D> {
251    #[inline]
252    fn put_common<A: codec::Encoder>(
253        &self,
254        buf: &mut BytesMut,
255        _encoder: &mut A,
256    ) -> Result<(), A::Error> {
257        buf.put_u32_le(0); // interface handle, shall be 0 for CIP
258        buf.put_u16_le(self.timeout); // timeout, 0 for SendUnitData
259        buf.put_u16_le(2); //  cpf item count
260        buf.put_slice(&[0, 0, 0, 0]); // null address
261        buf.put_u16_le(0xB2); // unconnected data item
262        buf.put_u16_le(self.data.bytes_count() as u16);
263        Ok(())
264    }
265}
266
267struct ConnectedData<D> {
268    connection_id: u32,
269    sequence_number: u16,
270    data: D,
271}
272
273impl<D: Encode> ConnectedData<D> {
274    #[inline]
275    fn put_common<A: codec::Encoder>(
276        &self,
277        buf: &mut BytesMut,
278        _encoder: &mut A,
279    ) -> Result<(), A::Error> {
280        buf.put_u32_le(0); // interface handle, shall be 0 for CIP
281        buf.put_u16_le(0); // timeout, 0 for SendUnitData
282        buf.put_u16_le(2); //  cpf item count
283
284        buf.put_u16_le(0xA1); // connected address item
285        buf.put_u16_le(4); // data len
286        buf.put_u32_le(self.connection_id);
287
288        buf.put_u16_le(0xB1); // connected data item
289        buf.put_u16_le(self.data.bytes_count() as u16 + 2); // data item len
290        buf.put_u16_le(self.sequence_number);
291        Ok(())
292    }
293}
294
295macro_rules! impl_data_encode {
296    ($ty:ident,$cnt:tt) => {
297        impl<D: Encode> Encode for $ty<D> {
298            #[inline]
299            fn encode<A: codec::Encoder>(
300                self,
301                buf: &mut BytesMut,
302                encoder: &mut A,
303            ) -> Result<(), A::Error>
304            where
305                Self: Sized,
306            {
307                self.put_common(buf, encoder)?;
308                self.data.encode_by_ref(buf, encoder)?; // data request
309                Ok(())
310            }
311
312            #[inline]
313            fn encode_by_ref<A: codec::Encoder>(
314                &self,
315                buf: &mut BytesMut,
316                encoder: &mut A,
317            ) -> Result<(), A::Error> {
318                self.put_common(buf, encoder)?;
319                self.data.encode_by_ref(buf, encoder)?; // data request
320                Ok(())
321            }
322
323            fn bytes_count(&self) -> usize {
324                $cnt + self.data.bytes_count()
325            }
326        }
327    };
328}
329
330impl_data_encode!(UnconnectedData, 16);
331impl_data_encode!(ConnectedData, 22);
332
333#[cfg(test)]
334mod test {
335    use super::*;
336    use rseip_core::tests::EncodeExt;
337
338    #[test]
339    fn test_list_identity_request() {
340        let buf = ListIdentity.try_into_bytes().unwrap();
341        assert_eq!(
342            &buf[..],
343            &[
344                0x63, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
345                0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
346            ]
347        )
348    }
349}