rseip_cip/codec/decode/
message_reply.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::*;
8use crate::{
9    connection::*,
10    error::{cip_error, cip_error_status},
11    Status,
12};
13use bytes::Buf;
14use rseip_core::{
15    cip::CommonPacketIter,
16    codec::{Decode, Decoder},
17    Either, Error,
18};
19
20#[inline]
21pub fn decode_service_and_status<'de, D>(mut decoder: D) -> Result<(u8, Status), D::Error>
22where
23    D: Decoder<'de>,
24{
25    decoder.ensure_size(4)?;
26    let reply_service = decoder.decode_u8(); // buf[0]
27    decoder.buf_mut().advance(1); // buf[1]
28    let general_status = decoder.decode_u8(); //buf[2]
29    let extended_status_size = decoder.decode_u8(); // buf[3]
30    decoder.ensure_size((extended_status_size * 2) as usize)?;
31    let extended_status = match extended_status_size {
32        0 => None,
33        1 => Some(decoder.decode_u16()),
34        v => return Err(Error::invalid_value("one of 0,1", v)),
35    };
36    let status = Status {
37        general: general_status,
38        extended: extended_status,
39    };
40
41    Ok((reply_service, status))
42}
43
44impl<'de, R> Decode<'de> for MessageReply<R>
45where
46    R: Decode<'de>,
47{
48    #[inline]
49    fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
50    where
51        D: Decoder<'de>,
52    {
53        let (reply_service, status) = decode_service_and_status(&mut decoder)?;
54        if status.is_err() {
55            return Err(cip_error_status(status));
56        }
57        let data = decoder.decode_any()?;
58        Ok(MessageReply::new(reply_service, status, data))
59    }
60}
61
62/// decode message reply from common packet for connected send
63///
64/// ```rust, ignore
65/// let data:(u16, MessageReply<T>) = decode_connected_send(cpf)?;
66/// ````
67#[inline]
68pub fn decode_connected_send<'de, D, R>(
69    mut cpf: CommonPacketIter<'de, D>,
70) -> Result<(u16, R), D::Error>
71where
72    D: Decoder<'de>,
73    R: Decode<'de> + 'static,
74{
75    if cpf.len() != 2 {
76        return Err(cip_error("common packet - expect 2 items"));
77    }
78    // should be connected address
79    ensure_connected_address(&mut cpf)?;
80    // should be connected data item
81    if let Some(res) = cpf.next_typed() {
82        let data_item: CommonPacketItem<(u16, _)> = res?;
83        data_item.ensure_type_code::<D::Error>(0xB1)?;
84        return Ok(data_item.data);
85    }
86    Err(cip_error("common packet - expect connected data item"))
87}
88
89/// decode message reply from common packet for unconnected send
90///
91/// ```rust, ignore
92/// let data:MessageReply<T>= decode_unconnected_send(cpf)?;
93/// ```
94#[inline]
95pub fn decode_unconnected_send<'de, D, R>(mut cpf: CommonPacketIter<'de, D>) -> Result<R, D::Error>
96where
97    D: Decoder<'de>,
98    R: Decode<'de> + 'static,
99{
100    if cpf.len() != 2 {
101        return Err(cip_error("common packet - expected 2 items"));
102    }
103    // should be null address
104    ensure_null_address(&mut cpf)?;
105
106    // should be unconnected data item
107    if let Some(res) = cpf.next_typed() {
108        let data_item: CommonPacketItem<_> = res?;
109        data_item.ensure_type_code::<D::Error>(0xB2)?;
110        return Ok(data_item.data);
111    }
112    Err(cip_error("common packet - expect connected data item"))
113}
114
115impl<'de> Decode<'de> for ForwardOpenReply {
116    #[inline]
117    fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
118    where
119        D: Decoder<'de>,
120    {
121        let (reply_service, status) = decode_service_and_status(&mut decoder)?;
122        let data = if status.is_err() {
123            let v = decode_forward_fail(decoder, status)?;
124            Either::Right(v)
125        } else {
126            let v = decode_forward_open_success(decoder)?;
127            Either::Left(v)
128        };
129        Ok(Self(MessageReply::new(reply_service, status, data)))
130    }
131}
132
133impl<'de> Decode<'de> for ForwardCloseReply {
134    #[inline]
135    fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
136    where
137        D: Decoder<'de>,
138    {
139        let (reply_service, status) = decode_service_and_status(&mut decoder)?;
140        let data = if status.is_err() {
141            let v = decode_forward_fail(decoder, status)?;
142            Either::Right(v)
143        } else {
144            let v = decode_forward_close_success(decoder)?;
145            Either::Left(v)
146        };
147        Ok(Self(MessageReply::new(reply_service, status, data)))
148    }
149}
150
151#[inline]
152fn decode_forward_open_success<'de, D>(mut decoder: D) -> Result<ForwardOpenSuccess, D::Error>
153where
154    D: Decoder<'de>,
155{
156    decoder.ensure_size(26)?;
157    let v = ForwardOpenSuccess {
158        o_t_connection_id: decoder.decode_u32(),
159        t_o_connection_id: decoder.decode_u32(),
160        connection_serial_number: decoder.decode_u16(),
161        originator_vendor_id: decoder.decode_u16(),
162        originator_serial_number: decoder.decode_u32(),
163        o_t_api: decoder.decode_u32(),
164        t_o_api: decoder.decode_u32(),
165        app_data: {
166            // buf[24], size in words
167            let app_data_size = 2 * decoder.decode_u8() as usize;
168            decoder.ensure_size(app_data_size)?;
169            decoder.buf_mut().advance(1); // reserved = buf[25]
170            decoder.buf_mut().copy_to_bytes(app_data_size)
171        },
172    };
173    Ok(v)
174}
175
176#[inline]
177fn decode_forward_close_success<'de, D>(mut decoder: D) -> Result<ForwardCloseSuccess, D::Error>
178where
179    D: Decoder<'de>,
180{
181    decoder.ensure_size(10)?;
182    let v = ForwardCloseSuccess {
183        connection_serial_number: decoder.decode_u16(), //  buf[0..2]
184        originator_vendor_id: decoder.decode_u16(),     // buf[2..4]
185        originator_serial_number: decoder.decode_u32(), // buf[4..8]
186        app_data: {
187            // buf[8], size in words
188            let app_data_size = 2 * decoder.decode_u8() as usize;
189            decoder.ensure_size(app_data_size)?;
190            decoder.buf_mut().advance(1); // reserved = buf[9]
191            decoder.buf_mut().copy_to_bytes(app_data_size)
192        },
193    };
194    Ok(v)
195}
196
197#[inline]
198fn decode_forward_fail<'de, D>(
199    mut decoder: D,
200    status: Status,
201) -> Result<ForwardRequestFail, D::Error>
202where
203    D: Decoder<'de>,
204{
205    let is_routing_error = status.is_routing_error();
206    let max_size = if is_routing_error { 9 } else { 8 };
207    decoder.ensure_size(max_size)?;
208    let res = ForwardRequestFail {
209        connection_serial_number: decoder.decode_u16(),
210        originator_vendor_id: decoder.decode_u16(),
211        originator_serial_number: decoder.decode_u32(),
212        remaining_path_size: if is_routing_error {
213            Some(decoder.decode_u8())
214        } else {
215            None
216        },
217    };
218    Ok(res)
219}
220
221#[inline]
222pub fn ensure_null_address<'de, D>(cpf: &mut CommonPacketIter<'de, D>) -> Result<(), D::Error>
223where
224    D: Decoder<'de>,
225{
226    if let Some(res) = cpf.next_item() {
227        let item = res?;
228        if item.type_code == 0 {
229            return Ok(());
230        }
231    }
232    Err(cip_error("common packet - expect null address"))
233}
234
235#[inline]
236pub fn ensure_connected_address<'de, D>(cpf: &mut CommonPacketIter<'de, D>) -> Result<(), D::Error>
237where
238    D: Decoder<'de>,
239{
240    if let Some(res) = cpf.next_item() {
241        let item = res?;
242        if item.type_code == 0xA1 {
243            return Ok(());
244        }
245    }
246    Err(cip_error("common packet - expect null address"))
247}