ads_proto/proto/
ams_header.rs

1use crate::error::AdsError;
2use crate::proto::ams_address::AmsAddress;
3use crate::proto::command_id::CommandID;
4use crate::proto::proto_traits::{Command, ReadFrom, WriteTo};
5use crate::proto::request::*;
6use crate::proto::response::*;
7use crate::proto::state_flags::StateFlags;
8use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
9use std::io::{self, Read, Write};
10use std::mem::swap;
11
12///Length of the fix part of the AMS Header in bytes
13const FIX_AMS_HEADER_LEN: u32 = 32;
14
15#[derive(Debug, Clone)]
16pub struct AmsTcpHeader {
17    reserved: [u8; 2],
18    pub length: u32,
19    pub ams_header: AmsHeader,
20}
21
22impl WriteTo for AmsTcpHeader {
23    fn write_to<W: Write>(&self, mut wtr: W) -> io::Result<()> {
24        wtr.write_all(&self.reserved)?;
25        wtr.write_u32::<LittleEndian>(self.ams_header.header_len())?;
26        self.ams_header.write_to(&mut wtr)?;
27        Ok(())
28    }
29}
30
31impl ReadFrom for AmsTcpHeader {
32    fn read_from<R: Read>(read: &mut R) -> io::Result<Self> {
33        let reserved = read.read_u16::<LittleEndian>()?.to_le_bytes();
34        Ok(AmsTcpHeader {
35            reserved,
36            length: read.read_u32::<LittleEndian>()?,
37            ams_header: AmsHeader::read_from(read)?,
38        })
39    }
40}
41
42impl From<AmsHeader> for AmsTcpHeader {
43    fn from(ams_header: AmsHeader) -> Self {
44        AmsTcpHeader {
45            reserved: [0, 0],
46            length: ams_header.header_len(),
47            ams_header,
48        }
49    }
50}
51
52#[derive(Debug, Clone)]
53pub struct AmsHeader {
54    ams_address_targed: AmsAddress,
55    ams_address_source: AmsAddress,
56    command_id: CommandID,
57    state_flags: StateFlags,
58    length: u32,
59    ams_ads_error: AdsError,
60    invoke_id: u32,
61    data: Vec<u8>,
62}
63
64impl WriteTo for AmsHeader {
65    fn write_to<W: Write>(&self, mut wtr: W) -> io::Result<()> {
66        self.ams_address_targed.write_to(&mut wtr)?;
67        self.ams_address_source.write_to(&mut wtr)?;
68        self.command_id.write_to(&mut wtr)?;
69        self.state_flags.write_to(&mut wtr)?;
70        wtr.write_u32::<LittleEndian>(self.length)?;
71        wtr.write_u32::<LittleEndian>(self.ams_ads_error.as_u32())?;
72        wtr.write_u32::<LittleEndian>(self.invoke_id)?;
73        wtr.write_all(&self.data)?;
74        Ok(())
75    }
76}
77
78impl ReadFrom for AmsHeader {
79    fn read_from<R: Read>(read: &mut R) -> io::Result<Self> {
80        let ams_address_targed = AmsAddress::read_from(read)?;
81        let ams_address_source = AmsAddress::read_from(read)?;
82        let command_id = CommandID::read_from(read)?;
83        let state_flags = StateFlags::read_from(read)?;
84        let length = read.read_u32::<LittleEndian>()?;
85        let ams_ads_error = AdsError::from(read.read_u32::<LittleEndian>()?);
86        let invoke_id = read.read_u32::<LittleEndian>()?;
87        let mut data: Vec<u8> = vec![0; length as usize];
88        read.read_exact(&mut data)?;
89
90        Ok(AmsHeader {
91            ams_address_targed,
92            ams_address_source,
93            command_id,
94            state_flags,
95            length,
96            ams_ads_error,
97            invoke_id,
98            data,
99        })
100    }
101}
102
103impl AmsHeader {
104    pub fn new(
105        ams_address_targed: AmsAddress,
106        ams_address_source: AmsAddress,
107        state_flags: StateFlags,
108        invoke_id: u32,
109        command: impl Command + WriteTo,
110    ) -> Self {
111        let mut data: Vec<u8> = Vec::with_capacity(16);
112        command
113            .write_to(&mut data)
114            .expect("failed to write request to buffer!");
115
116        AmsHeader {
117            ams_address_targed,
118            ams_address_source,
119            command_id: command.command_id(),
120            state_flags,
121            length: data.len() as u32,
122            ams_ads_error: AdsError::ErrNoError,
123            invoke_id,
124            data,
125        }
126    }
127
128    ///Returns the response from AMS header data
129    pub fn response(&mut self) -> io::Result<Response> {
130        if self.state_flags.is_response() || self.command_id == CommandID::DeviceNotification {
131            match self.command_id {
132                CommandID::Invalid => Err(io::Error::new(
133                    io::ErrorKind::Other,
134                    AdsError::AdsErrDeviceInvalidData,
135                )),
136                CommandID::ReadDeviceInfo => Ok(Response::ReadDeviceInfo(
137                    ReadDeviceInfoResponse::read_from(&mut self.data.as_slice())?,
138                )),
139                CommandID::Read => Ok(Response::Read(ReadResponse::read_from(
140                    &mut self.data.as_slice(),
141                )?)),
142                CommandID::Write => Ok(Response::Write(WriteResponse::read_from(
143                    &mut self.data.as_slice(),
144                )?)),
145                CommandID::ReadState => Ok(Response::ReadState(ReadStateResponse::read_from(
146                    &mut self.data.as_slice(),
147                )?)),
148                CommandID::WriteControl => Ok(Response::WriteControl(
149                    WriteControlResponse::read_from(&mut self.data.as_slice())?,
150                )),
151                CommandID::AddDeviceNotification => Ok(Response::AddDeviceNotification(
152                    AddDeviceNotificationResponse::read_from(&mut self.data.as_slice())?,
153                )),
154                CommandID::DeleteDeviceNotification => Ok(Response::DeleteDeviceNotification(
155                    DeleteDeviceNotificationResponse::read_from(&mut self.data.as_slice())?,
156                )),
157                CommandID::DeviceNotification => Ok(Response::DeviceNotification(
158                    AdsNotificationStream::read_from(&mut self.data.as_slice())?,
159                )),
160                CommandID::ReadWrite => Ok(Response::ReadWrite(ReadWriteResponse::read_from(
161                    &mut self.data.as_slice(),
162                )?)),
163            }
164        } else {
165            Err(io::Error::new(
166                io::ErrorKind::Other,
167                "Is not a response but a request!",
168            ))
169        }
170    }
171
172    ///Returns the request from AMS header data
173    pub fn request(&mut self) -> io::Result<Request> {
174        if !self.state_flags.is_response() {
175            match self.command_id {
176                CommandID::Invalid => Err(io::Error::new(
177                    io::ErrorKind::Other,
178                    AdsError::AdsErrDeviceInvalidData,
179                )),
180                CommandID::ReadDeviceInfo => {
181                    Ok(Request::ReadDeviceInfo(ReadDeviceInfoRequest::new()))
182                }
183                CommandID::Read => Ok(Request::Read(ReadRequest::read_from(
184                    &mut self.data.as_slice(),
185                )?)),
186                CommandID::Write => Ok(Request::Write(WriteRequest::read_from(
187                    &mut self.data.as_slice(),
188                )?)),
189                CommandID::ReadState => Ok(Request::ReadState(ReadStateRequest::new())),
190                CommandID::WriteControl => Ok(Request::WriteControl(
191                    WriteControlRequest::read_from(&mut self.data.as_slice())?,
192                )),
193                CommandID::AddDeviceNotification => Ok(Request::AddDeviceNotification(
194                    AddDeviceNotificationRequest::read_from(&mut self.data.as_slice())?,
195                )),
196                CommandID::DeleteDeviceNotification => Ok(Request::DeleteDeviceNotification(
197                    DeleteDeviceNotificationRequest::read_from(&mut self.data.as_slice())?,
198                )),
199                CommandID::DeviceNotification => {
200                    Ok(Request::DeviceNotification(DeviceNotificationRequest::new()))
201                }
202                CommandID::ReadWrite => Ok(Request::ReadWrite(ReadWriteRequest::read_from(
203                    &mut self.data.as_slice(),
204                )?)),
205            }
206        } else {
207            Err(io::Error::new(
208                io::ErrorKind::Other,
209                "Is not a request but a response!",
210            ))
211        }
212    }
213
214    ///Returns the command id from the ams header
215    pub fn command_id(&self) -> CommandID {
216        self.command_id
217    }
218
219    ///Returns the invoke id from the ams header. This is the invoke id set when requested the data
220    pub fn invoke_id(&self) -> u32 {
221        self.invoke_id
222    }
223
224    ///Returns the ads error code from the ams header. There is another ads error in the response data!
225    pub fn ads_error(&self) -> &AdsError {
226        &self.ams_ads_error
227    }
228
229    ///Return the raw data from the ams header data section. This data can be used to create the specific response object.
230    pub fn raw_response_data(&self) -> &[u8] {
231        &self.data[..]
232    }
233
234    ///Get the ads error code from the response data (ams header data section)
235    pub fn response_result(&self) -> Option<AdsError> {
236        if self.data.len() >= 4 {
237            if let Ok(result) = self.data.as_slice().read_u32::<LittleEndian>() {
238                return Some(AdsError::from(result));
239            }
240        }
241        None
242    }
243
244    ///get the length in bytes of the whole ams_header.
245    fn header_len(&self) -> u32 {
246        self.data.len() as u32 + FIX_AMS_HEADER_LEN
247    }
248
249    ///get data length in bytes of the ams header data section
250    pub fn data_len(&self) -> u32 {
251        self.length
252    }
253
254    /// update command id, payload data and state flags.
255    /// for example when changing the AmsHeader from request to response instead of cerating a new one
256    /// see also swap_address()
257    pub fn update_command(
258        &mut self,
259        command: impl Command + WriteTo,
260        state_flag: StateFlags,
261    ) -> io::Result<()> {
262        self.command_id = command.command_id();
263        self.data.clear();
264        command.write_to(&mut self.data)?;
265        self.length = self.data.len() as u32;
266        self.state_flags = state_flag;
267        Ok(())
268    }
269
270    /// update ams header data
271    /// updates the payload data and the data length info in the ams header
272    pub fn update_raw_data(&mut self, buffer: Vec<u8>) -> io::Result<()> {
273        self.data = buffer;
274        self.length = self.data.len() as u32;
275        Ok(())
276    }
277
278    /// Swap targed and source AmsAddress
279    pub fn swap_address(&mut self) {
280        swap(&mut self.ams_address_source, &mut self.ams_address_targed);
281    }
282}
283
284#[cfg(test)]
285mod tests {
286    use super::*;
287    use crate::proto::ams_address::*;
288    use std::str::FromStr;
289    #[test]
290    fn ams_header_write_to_test() {
291        let mut buffer: Vec<u8> = Vec::new();
292
293        let port = 30000;
294
295        let ams_header = AmsHeader::new(
296            AmsAddress::new(AmsNetId::from_str("192.168.1.1.1.1").unwrap(), port),
297            AmsAddress::new(AmsNetId::new(192, 168, 1, 1, 1, 2), port),
298            StateFlags::resp_default(),
299            111,
300            Request::Read(ReadRequest::new(259, 259, 4)),
301        );
302
303        ams_header.write_to(&mut buffer).unwrap();
304
305        #[rustfmt::skip]
306        let compare: Vec<u8> = vec![
307            //target AmsAddress -> NetId/port (192.168.1.1.1.1, 30000)
308            192, 168, 1, 1, 1, 1, 48, 117,
309            //Source AmsAddress -> NetId/port (192.168.1.1.1.2, 30000)
310            192, 168, 1, 1, 1, 2, 48, 117,
311            //CommandID -> Read 
312            2, 0,                               
313            //state flag -> Request, Ads command, TCP (4)
314            5, 0,                               
315            //Lennth of data for read request (12 byte)
316            12, 0, 0, 0,                        
317            //Error code -> No error 
318            0, 0, 0, 0,                         
319            //Invoke ID -> 111 
320            111, 0, 0, 0,                       
321            //Data from read request -> see request.rs
322            3, 1, 0, 0, 3, 1, 0, 0, 4, 0, 0, 0  
323        ];
324        assert_eq!(compare, buffer);
325    }
326
327    #[test]
328    fn ams_header_read_from_test() {
329        #[rustfmt::skip]
330        let data: Vec<u8> = vec![
331            //target AmsAddress -> NetId/port (192.168.1.1.1.1, 30000)
332            192, 168, 1, 1, 1, 1, 48, 117,
333            //Source AmsAddress -> NetId/port (192.168.1.1.1.2, 30000)
334            192, 168, 1, 1, 1, 2, 48, 117,      
335            //CommandID -> Read 
336            2, 0,                               
337            //state flag -> Request, Ads command, TCP (4)
338            4, 0,                               
339            //Lennth of data for read request (12 byte)
340            12, 0, 0, 0,                        
341            //Error code -> No error 
342            0, 0, 0, 0,                         
343            //Invoke ID -> 111 
344            111, 0, 0, 0,                       
345            //Data from read request -> see request.rs
346            3, 1, 0, 0, 3, 1, 0, 0, 4, 0, 0, 0  
347        ];
348
349        let ams_header = AmsHeader::read_from(&mut data.as_slice()).unwrap();
350        assert_eq!(
351            ams_header.ams_address_targed.ams_net_id.net_id(),
352            [192, 168, 1, 1, 1, 1]
353        );
354        assert_eq!(
355            ams_header.ams_address_source.ams_net_id.net_id(),
356            [192, 168, 1, 1, 1, 2]
357        );
358        assert_eq!(ams_header.ams_address_targed.port, 30000);
359        assert_eq!(ams_header.ams_address_source.port, 30000);
360        assert_eq!(ams_header.command_id, CommandID::Read);
361        assert_eq!(ams_header.state_flags.value(), 4);
362        assert_eq!(ams_header.length, 12, "Wrong data length");
363        assert_eq!(ams_header.ams_ads_error, AdsError::ErrNoError);
364        assert_eq!(ams_header.invoke_id, 111);
365        assert_eq!(ams_header.data, [3, 1, 0, 0, 3, 1, 0, 0, 4, 0, 0, 0]);
366    }
367
368    #[test]
369    fn ams_header_len_test() {
370        let port = 30000;
371        let ams_header = AmsHeader::new(
372            AmsAddress::new(AmsNetId::from_str("192.168.1.1.1.1").unwrap(), port),
373            AmsAddress::new(AmsNetId::new(192, 168, 1, 1, 1, 2), port),
374            StateFlags::req_default(),
375            111,
376            Request::Read(ReadRequest::new(259, 259, 4)),
377        );
378
379        assert_eq!(ams_header.header_len(), 44);
380    }
381
382    #[test]
383    fn ams_header_swap_address() {
384        let port = 30000;
385        let mut ams_header = AmsHeader::new(
386            AmsAddress::new(AmsNetId::from_str("192.168.1.1.1.1").unwrap(), port),
387            AmsAddress::new(AmsNetId::new(192, 168, 1, 1, 1, 2), port),
388            StateFlags::req_default(),
389            111,
390            Request::Read(ReadRequest::new(259, 259, 4)),
391        );
392
393        //before swap
394        assert_eq!(
395            ams_header.ams_address_targed,
396            AmsAddress::new(AmsNetId::from_str("192.168.1.1.1.1").unwrap(), port)
397        );
398        assert_eq!(
399            ams_header.ams_address_source,
400            AmsAddress::new(AmsNetId::new(192, 168, 1, 1, 1, 2), port)
401        );
402
403        ams_header.swap_address();
404
405        //After swap
406        assert_eq!(
407            ams_header.ams_address_targed,
408            AmsAddress::new(AmsNetId::new(192, 168, 1, 1, 1, 2), port)
409        );
410        assert_eq!(
411            ams_header.ams_address_source,
412            AmsAddress::new(AmsNetId::from_str("192.168.1.1.1.1").unwrap(), port)
413        );
414    }
415
416    #[test]
417    fn ams_tcp_header_write_to_test() {
418        let mut buffer: Vec<u8> = Vec::new();
419
420        let port = 30000;
421
422        let ams_header = AmsHeader::new(
423            AmsAddress::new(AmsNetId::from_str("192.168.1.1.1.1").unwrap(), port),
424            AmsAddress::new(AmsNetId::new(192, 168, 1, 1, 1, 2), port),
425            StateFlags::req_default(),
426            111,
427            Request::Read(ReadRequest::new(259, 259, 4)),
428        );
429
430        let ams_tcp_header = AmsTcpHeader::from(ams_header);
431        ams_tcp_header.write_to(&mut buffer).unwrap();
432
433        #[rustfmt::skip]
434        let compare: Vec<u8> = vec![
435            //Reserved has to be 0
436            0,0,
437            //Length in bytes of AmsHeader
438            44, 0, 0, 0,
439            //target AmsAddress -> NetId/port (192.168.1.1.1.1, 30000)
440            192, 168, 1, 1, 1, 1, 48, 117,      
441            //Source AmsAddress -> NetId/port (192.168.1.1.1.2, 30000)
442            192, 168, 1, 1, 1, 2, 48, 117,      
443            //CommandID -> Read 
444            2, 0,                               
445            //state flag -> Request, Ads command, TCP (4)
446            4, 0,                               
447            //Lennth of data for read request (12 byte)
448            12, 0, 0, 0,                        
449            //Error code -> No error 
450            0, 0, 0, 0,                         
451            //Invoke ID -> 111 
452            111, 0, 0, 0,                       
453            //Data from read request -> see request.rs
454            3, 1, 0, 0, 3, 1, 0, 0, 4, 0, 0, 0  
455        ];
456        assert_eq!(compare, buffer);
457    }
458
459    #[test]
460    fn ams_tcp_header_read_from_test() {
461        #[rustfmt::skip]
462        let data: Vec<u8> = vec![
463          //Reserved has to be 0
464          0,0,
465          //Length in bytes of AmsHeader
466          44, 0, 0, 0,
467          //target AmsAddress -> NetId/port (192.168.1.1.1.1, 30000)
468          192, 168, 1, 1, 1, 1, 48, 117,      
469          //Source AmsAddress -> NetId/port (192.168.1.1.1.2, 30000)
470          192, 168, 1, 1, 1, 2, 48, 117,      
471          //CommandID -> Read 
472          2, 0,                               
473          //state flag -> Request, Ads command, TCP (4)
474          4, 0,                               
475          //Lennth of data for read request (12 byte)
476          12, 0, 0, 0,                        
477          //Error code -> No error 
478          0, 0, 0, 0,                         
479          //Invoke ID -> 111 
480          111, 0, 0, 0,                       
481          //Data from read request -> see request.rs
482          3, 1, 0, 0, 3, 1, 0, 0, 4, 0, 0, 0  
483        ];
484
485        let ams_tcp_header = AmsTcpHeader::read_from(&mut data.as_slice()).unwrap();
486        assert_eq!(ams_tcp_header.reserved, [0, 0]);
487        assert_eq!(ams_tcp_header.length, 44);
488        assert_eq!(
489            ams_tcp_header
490                .ams_header
491                .ams_address_targed
492                .ams_net_id
493                .net_id(),
494            [192, 168, 1, 1, 1, 1]
495        );
496        assert_eq!(
497            ams_tcp_header
498                .ams_header
499                .ams_address_source
500                .ams_net_id
501                .net_id(),
502            [192, 168, 1, 1, 1, 2]
503        );
504        assert_eq!(ams_tcp_header.ams_header.ams_address_targed.port, 30000);
505        assert_eq!(ams_tcp_header.ams_header.ams_address_source.port, 30000);
506        assert_eq!(ams_tcp_header.ams_header.command_id, CommandID::Read);
507        assert_eq!(ams_tcp_header.ams_header.state_flags.value(), 4);
508        assert_eq!(ams_tcp_header.ams_header.length, 12);
509        assert_eq!(
510            ams_tcp_header.ams_header.ams_ads_error,
511            AdsError::ErrNoError
512        );
513        assert_eq!(ams_tcp_header.ams_header.invoke_id, 111);
514        assert_eq!(
515            ams_tcp_header.ams_header.data,
516            [3, 1, 0, 0, 3, 1, 0, 0, 4, 0, 0, 0]
517        );
518    }
519
520    #[test]
521    fn ams_tcp_header_command_id() {
522        let data: Vec<u8> = vec![
523            //Reserved has to be 0
524            0, 0, //Length in bytes of AmsHeader
525            44, 0, 0, 0, //target AmsAddress -> NetId/port (192.168.1.1.1.1, 30000)
526            192, 168, 1, 1, 1, 1, 48, 117,
527            //Source AmsAddress -> NetId/port (192.168.1.1.1.2, 30000)
528            192, 168, 1, 1, 1, 2, 48, 117, //CommandID -> Read
529            2, 0, //state flag -> Request, Ads command, TCP (4)
530            4, 0, //Lennth of data for read request (12 byte)
531            12, 0, 0, 0, //Error code -> No error
532            0, 0, 0, 0, //Invoke ID -> 111
533            111, 0, 0, 0, //Data from read request -> see request.rs
534            3, 1, 0, 0, 3, 1, 0, 0, 4, 0, 0, 0,
535        ];
536
537        let ams_tcp_header = AmsTcpHeader::read_from(&mut data.as_slice()).unwrap();
538        assert_eq!(CommandID::Read, ams_tcp_header.ams_header.command_id());
539    }
540
541    #[test]
542    fn ams_tcp_header_response_data_length() {
543        let data: Vec<u8> = vec![
544            //Reserved has to be 0
545            0, 0, //Length in bytes of AmsHeader
546            44, 0, 0, 0, //target AmsAddress -> NetId/port (192.168.1.1.1.1, 30000)
547            192, 168, 1, 1, 1, 1, 48, 117,
548            //Source AmsAddress -> NetId/port (192.168.1.1.1.2, 30000)
549            192, 168, 1, 1, 1, 2, 48, 117, //CommandID -> Read
550            2, 0, //state flag -> Request, Ads command, TCP (4)
551            4, 0, //Lennth of data for read request (12 byte)
552            12, 0, 0, 0, //Error code -> No error
553            0, 0, 0, 0, //Invoke ID -> 111
554            111, 0, 0, 0, //Data from read request -> see request.rs
555            3, 1, 0, 0, 3, 1, 0, 0, 4, 0, 0, 0,
556        ];
557
558        let ams_tcp_header = AmsTcpHeader::read_from(&mut data.as_slice()).unwrap();
559        let len = ams_tcp_header.ams_header.data_len();
560        assert_eq!(12, len);
561    }
562
563    #[test]
564    fn ams_tcp_header_update_command() {
565        let data: Vec<u8> = vec![
566            //Reserved has to be 0
567            0, 0, //Length in bytes of AmsHeader
568            44, 0, 0, 0, //target AmsAddress -> NetId/port (192.168.1.1.1.1, 30000)
569            192, 168, 1, 1, 1, 1, 48, 117,
570            //Source AmsAddress -> NetId/port (192.168.1.1.1.2, 30000)
571            192, 168, 1, 1, 1, 2, 48, 117, //CommandID -> Read
572            2, 0, //state flag -> Request, Ads command, TCP (4)
573            4, 0, //Lennth of data for read request (12 byte)
574            12, 0, 0, 0, //Error code -> No error
575            0, 0, 0, 0, //Invoke ID -> 111
576            111, 0, 0, 0, //Data from read request -> see request.rs
577            3, 1, 0, 0, 3, 1, 0, 0, 4, 0, 0, 0,
578        ];
579
580        let mut ams_tcp_header = AmsTcpHeader::read_from(&mut data.as_slice()).unwrap();
581        let request = Request::ReadDeviceInfo(ReadDeviceInfoRequest::new());
582        let mut new_data: Vec<u8> = Vec::new();
583        request.write_to(&mut new_data).unwrap();
584        ams_tcp_header
585            .ams_header
586            .update_command(request, StateFlags::req_default())
587            .unwrap();
588        assert_eq!(new_data, ams_tcp_header.ams_header.raw_response_data());
589        assert_eq!(
590            ams_tcp_header.ams_header.command_id(),
591            CommandID::ReadDeviceInfo
592        );
593    }
594
595    #[test]
596    fn ams_tcp_header_update_data() {
597        let data: Vec<u8> = vec![
598            //Reserved has to be 0
599            0, 0, //Length in bytes of AmsHeader
600            44, 0, 0, 0, //target AmsAddress -> NetId/port (192.168.1.1.1.1, 30000)
601            192, 168, 1, 1, 1, 1, 48, 117,
602            //Source AmsAddress -> NetId/port (192.168.1.1.1.2, 30000)
603            192, 168, 1, 1, 1, 2, 48, 117, //CommandID -> Read
604            2, 0, //state flag -> Request, Ads command, TCP (4)
605            4, 0, //Lennth of data for read request (12 byte)
606            12, 0, 0, 0, //Error code -> No error
607            0, 0, 0, 0, //Invoke ID -> 111
608            111, 0, 0, 0, //Data from read request -> see request.rs
609            3, 1, 0, 0, 3, 1, 0, 0, 4, 0, 0, 0,
610        ];
611
612        let mut ams_tcp_header = AmsTcpHeader::read_from(&mut data.as_slice()).unwrap();
613        let new_data: Vec<u8> = vec![111, 0, 0, 0, 3, 1, 0, 0, 1, 3, 0, 0, 8, 0]; //2 byte shorter
614        ams_tcp_header
615            .ams_header
616            .update_raw_data(new_data.clone())
617            .unwrap();
618        assert_eq!(new_data, ams_tcp_header.ams_header.raw_response_data());
619        assert_eq!(
620            new_data.len(),
621            ams_tcp_header.ams_header.raw_response_data().len()
622        );
623        assert_eq!(new_data.len(), 14);
624    }
625
626    #[test]
627    fn ams_tcp_header_invoke_id() {
628        let data: Vec<u8> = vec![
629            //Reserved has to be 0
630            0, 0, //Length in bytes of AmsHeader
631            44, 0, 0, 0, //target AmsAddress -> NetId/port (192.168.1.1.1.1, 30000)
632            192, 168, 1, 1, 1, 1, 48, 117,
633            //Source AmsAddress -> NetId/port (192.168.1.1.1.2, 30000)
634            192, 168, 1, 1, 1, 2, 48, 117, //CommandID -> Read
635            2, 0, //state flag -> Request, Ads command, TCP (4)
636            4, 0, //Lennth of data for read request (12 byte)
637            12, 0, 0, 0, //Error code -> No error
638            0, 0, 0, 0, //Invoke ID -> 111
639            111, 0, 0, 0, //Data from read request -> see request.rs
640            3, 1, 0, 0, 3, 1, 0, 0, 4, 0, 0, 0,
641        ];
642
643        let ams_tcp_header = AmsTcpHeader::read_from(&mut data.as_slice()).unwrap();
644        assert_eq!(111, ams_tcp_header.ams_header.invoke_id());
645    }
646
647    #[test]
648    fn ams_tcp_header_ads_error() {
649        let data: Vec<u8> = vec![
650            //Reserved has to be 0
651            0, 0, //Length in bytes of AmsHeader
652            44, 0, 0, 0, //target AmsAddress -> NetId/port (192.168.1.1.1.1, 30000)
653            192, 168, 1, 1, 1, 1, 48, 117,
654            //Source AmsAddress -> NetId/port (192.168.1.1.1.2, 30000)
655            192, 168, 1, 1, 1, 2, 48, 117, //CommandID -> Read
656            2, 0, //state flag -> Request, Ads command, TCP (4)
657            4, 0, //Lennth of data for read request (12 byte)
658            12, 0, 0, 0, //Error code -> No error
659            0, 0, 0, 0, //Invoke ID -> 111
660            111, 0, 0, 0, //Data from read request -> see request.rs
661            3, 1, 0, 0, 3, 1, 0, 0, 4, 0, 0, 0,
662        ];
663
664        let ams_tcp_header = AmsTcpHeader::read_from(&mut data.as_slice()).unwrap();
665        assert_eq!(&AdsError::ErrNoError, ams_tcp_header.ams_header.ads_error());
666    }
667
668    #[test]
669    fn ams_tcp_header_raw_response_data() {
670        let data: Vec<u8> = vec![
671            //Reserved has to be 0
672            0, 0, //Length in bytes of AmsHeader
673            44, 0, 0, 0, //target AmsAddress -> NetId/port (192.168.1.1.1.1, 30000)
674            192, 168, 1, 1, 1, 1, 48, 117,
675            //Source AmsAddress -> NetId/port (192.168.1.1.1.2, 30000)
676            192, 168, 1, 1, 1, 2, 48, 117, //CommandID -> Read
677            2, 0, //state flag -> Request, Ads command, TCP (4)
678            4, 0, //Lennth of data for read request (12 byte)
679            12, 0, 0, 0, //Error code -> No error
680            0, 0, 0, 0, //Invoke ID -> 111
681            111, 0, 0, 0, //Data from read request -> see request.rs
682            3, 1, 0, 0, 3, 1, 0, 0, 4, 0, 0, 0,
683        ];
684
685        let ams_tcp_header = AmsTcpHeader::read_from(&mut data.as_slice()).unwrap();
686        assert_eq!(
687            &[3, 1, 0, 0, 3, 1, 0, 0, 4, 0, 0, 0],
688            ams_tcp_header.ams_header.raw_response_data()
689        );
690    }
691
692    #[test]
693    fn ams_tcp_header_responser_result() {
694        let data: Vec<u8> = vec![
695            //Reserved has to be 0
696            0, 0, //Length in bytes of AmsHeader
697            44, 0, 0, 0, //target AmsAddress -> NetId/port (192.168.1.1.1.1, 30000)
698            192, 168, 1, 1, 1, 1, 48, 117,
699            //Source AmsAddress -> NetId/port (192.168.1.1.1.2, 30000)
700            192, 168, 1, 1, 1, 2, 48, 117, //CommandID -> Read
701            2, 0, //state flag -> Request, Ads command, TCP (4)
702            4, 0, //Lennth of data for read request (12 byte)
703            12, 0, 0, 0, //Error code -> No error
704            1, 0, 0, 0, //Invoke ID -> 111
705            111, 0, 0, 0, //Data from read request -> see request.rs
706            3, 1, 0, 0, 3, 1, 0, 0, 4, 0, 0, 0,
707        ];
708
709        let ams_tcp_header = AmsTcpHeader::read_from(&mut data.as_slice()).unwrap();
710        assert_eq!(
711            Some(AdsError::ErrUnknowAdsError { error_code: 259 }),
712            ams_tcp_header.ams_header.response_result()
713        );
714    }
715}