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
12const 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 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 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 pub fn command_id(&self) -> CommandID {
216 self.command_id
217 }
218
219 pub fn invoke_id(&self) -> u32 {
221 self.invoke_id
222 }
223
224 pub fn ads_error(&self) -> &AdsError {
226 &self.ams_ads_error
227 }
228
229 pub fn raw_response_data(&self) -> &[u8] {
231 &self.data[..]
232 }
233
234 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 fn header_len(&self) -> u32 {
246 self.data.len() as u32 + FIX_AMS_HEADER_LEN
247 }
248
249 pub fn data_len(&self) -> u32 {
251 self.length
252 }
253
254 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 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 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 192, 168, 1, 1, 1, 1, 48, 117,
309 192, 168, 1, 1, 1, 2, 48, 117,
311 2, 0,
313 5, 0,
315 12, 0, 0, 0,
317 0, 0, 0, 0,
319 111, 0, 0, 0,
321 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 192, 168, 1, 1, 1, 1, 48, 117,
333 192, 168, 1, 1, 1, 2, 48, 117,
335 2, 0,
337 4, 0,
339 12, 0, 0, 0,
341 0, 0, 0, 0,
343 111, 0, 0, 0,
345 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 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 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 0,0,
437 44, 0, 0, 0,
439 192, 168, 1, 1, 1, 1, 48, 117,
441 192, 168, 1, 1, 1, 2, 48, 117,
443 2, 0,
445 4, 0,
447 12, 0, 0, 0,
449 0, 0, 0, 0,
451 111, 0, 0, 0,
453 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 0,0,
465 44, 0, 0, 0,
467 192, 168, 1, 1, 1, 1, 48, 117,
469 192, 168, 1, 1, 1, 2, 48, 117,
471 2, 0,
473 4, 0,
475 12, 0, 0, 0,
477 0, 0, 0, 0,
479 111, 0, 0, 0,
481 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 0, 0, 44, 0, 0, 0, 192, 168, 1, 1, 1, 1, 48, 117,
527 192, 168, 1, 1, 1, 2, 48, 117, 2, 0, 4, 0, 12, 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, 0, 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 0, 0, 44, 0, 0, 0, 192, 168, 1, 1, 1, 1, 48, 117,
548 192, 168, 1, 1, 1, 2, 48, 117, 2, 0, 4, 0, 12, 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, 0, 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 0, 0, 44, 0, 0, 0, 192, 168, 1, 1, 1, 1, 48, 117,
570 192, 168, 1, 1, 1, 2, 48, 117, 2, 0, 4, 0, 12, 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, 0, 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 0, 0, 44, 0, 0, 0, 192, 168, 1, 1, 1, 1, 48, 117,
602 192, 168, 1, 1, 1, 2, 48, 117, 2, 0, 4, 0, 12, 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, 0, 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]; 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 0, 0, 44, 0, 0, 0, 192, 168, 1, 1, 1, 1, 48, 117,
633 192, 168, 1, 1, 1, 2, 48, 117, 2, 0, 4, 0, 12, 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, 0, 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 0, 0, 44, 0, 0, 0, 192, 168, 1, 1, 1, 1, 48, 117,
654 192, 168, 1, 1, 1, 2, 48, 117, 2, 0, 4, 0, 12, 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, 0, 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 0, 0, 44, 0, 0, 0, 192, 168, 1, 1, 1, 1, 48, 117,
675 192, 168, 1, 1, 1, 2, 48, 117, 2, 0, 4, 0, 12, 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, 0, 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 0, 0, 44, 0, 0, 0, 192, 168, 1, 1, 1, 1, 48, 117,
699 192, 168, 1, 1, 1, 2, 48, 117, 2, 0, 4, 0, 12, 0, 0, 0, 1, 0, 0, 0, 111, 0, 0, 0, 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}