iso13400_2/response/
mod.rs

1use crate::{error::Error, utils, *};
2use getset::{CopyGetters, Getters};
3use std::fmt::{Display, Formatter};
4
5#[derive(Debug, Clone, Eq, PartialEq, CopyGetters)]
6#[get_copy = "pub"]
7pub struct HeaderNegative {
8    pub(crate) code: HeaderNegativeCode,
9}
10
11impl HeaderNegative {
12    pub fn new(code: HeaderNegativeCode) -> Self {
13        Self { code }
14    }
15
16    #[inline]
17    const fn length() -> usize {
18        1
19    }
20}
21
22impl TryFrom<&[u8]> for HeaderNegative {
23    type Error = Error;
24    fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
25        let (_, offset) = utils::data_len_check(data, Self::length(), true)?;
26        let code = data[offset];
27        let code = HeaderNegativeCode::from(code);
28
29        Ok(Self { code })
30    }
31}
32
33impl From<HeaderNegative> for Vec<u8> {
34    fn from(val: HeaderNegative) -> Self {
35        let mut result = HEADER_NEGATIVE.to_be_bytes().to_vec();
36        let length = HeaderNegative::length() as u32;
37        result.extend(length.to_be_bytes());
38        result.push(val.code.into());
39
40        result
41    }
42}
43
44/****** --- UDP --- ********/
45
46/// response with delay
47/// send response 3 times with interval 500ms
48/// the RoutingActive from client must be 0xE0 when further_act = 0x10.
49#[derive(Debug, Clone, Eq, PartialEq, Getters, CopyGetters)]
50pub struct VehicleID {
51    // 0x0004
52    #[get = "pub"]
53    pub(crate) vin: String,
54    #[get_copy = "pub"]
55    pub(crate) address: LogicAddress,
56    #[get_copy = "pub"]
57    pub(crate) eid: Eid,
58    #[get_copy = "pub"]
59    pub(crate) gid: Gid,
60    #[get_copy = "pub"]
61    pub(crate) further_act: FurtherAction,
62    #[get_copy = "pub"]
63    pub(crate) sync_status: Option<SyncStatus>,
64}
65
66impl VehicleID {
67    pub fn new(
68        vin: String,
69        address: LogicAddress,
70        eid: Eid,
71        gid: Eid,
72        further_act: FurtherAction,
73        sync_status: Option<SyncStatus>,
74    ) -> Result<Self, Error> {
75        let vin_len = vin.len();
76        if vin_len != LENGTH_OF_VIN {
77            return Err(Error::InvalidParam(format!(
78                "length of vin must equal {}",
79                LENGTH_OF_VIN
80            )));
81        }
82
83        Ok(Self {
84            vin,
85            address,
86            eid,
87            gid,
88            further_act,
89            sync_status,
90        })
91    }
92
93    /// min length
94    #[inline]
95    const fn length() -> usize {
96        LENGTH_OF_VIN + SIZE_OF_ADDRESS + Eid::length() + Gid::length() + 1
97    }
98}
99
100impl TryFrom<&[u8]> for VehicleID {
101    type Error = Error;
102    fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
103        let (data_len, mut offset) = utils::data_len_check(data, Self::length(), false)?;
104        let vin = match String::from_utf8(data[offset..offset + LENGTH_OF_VIN].to_vec()) {
105            Ok(v) => v,
106            Err(_) => {
107                rsutil::warn!("invalid UTF-8 string: {}", hex::encode(data));
108                "-".repeat(data_len)
109            }
110        };
111        offset += LENGTH_OF_VIN;
112        let address =
113            u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
114        offset += SIZE_OF_ADDRESS;
115        let address = LogicAddress::from(address);
116        let eid = Eid::try_from(&data[offset..])?;
117        offset += Eid::length();
118        let gid = Gid::try_from(&data[offset..])?;
119        offset += Gid::length();
120        let further_act = FurtherAction::from(data[offset]);
121        offset += 1;
122        let sync_status = match data_len - offset {
123            0 => Ok(None),
124            1 => Ok(Some(SyncStatus::from(data[offset]))),
125            _ => Err(Error::InvalidLength {
126                actual: data_len,
127                expected: Self::length() + 1,
128            }),
129        }?;
130
131        Ok(Self {
132            vin,
133            address,
134            eid,
135            gid,
136            further_act,
137            sync_status,
138        })
139    }
140}
141
142impl From<VehicleID> for Vec<u8> {
143    fn from(val: VehicleID) -> Self {
144        let mut result = UDP_RESP_VEHICLE_IDENTIFIER.to_be_bytes().to_vec();
145        let mut length = VehicleID::length() as u32;
146        if val.sync_status.is_some() {
147            length += 1;
148        }
149        result.extend(length.to_be_bytes());
150        result.extend(val.vin.as_bytes());
151        let address: u16 = val.address.into();
152        result.extend(address.to_be_bytes());
153        result.append(&mut val.eid.into());
154        result.append(&mut val.gid.into());
155        result.push(val.further_act.into());
156        if let Some(status) = val.sync_status {
157            result.push(status.into());
158        }
159
160        result
161    }
162}
163
164#[derive(Debug, Clone, Eq, PartialEq, CopyGetters)]
165#[get_copy = "pub"]
166pub struct EntityStatus {
167    // 0x4002
168    pub(crate) node_type: NodeType,
169    /// 1 ~ 255
170    pub(crate) mcts: u8, // Max. concurrent TCP_DATA sockets
171    /// 0 ~ 255
172    pub(crate) ncts: u8, // Current opened TCP_DATA sockets
173    /// 0 ~ 4GB
174    pub(crate) max_data_size: Option<u32>,
175}
176
177impl EntityStatus {
178    pub fn new(node_type: NodeType, mcts: u8, ncts: u8, max_data_size: Option<u32>) -> Self {
179        Self {
180            node_type,
181            mcts,
182            ncts,
183            max_data_size,
184        }
185    }
186
187    /// min length
188    #[inline]
189    const fn length() -> usize {
190        1 + 1 + 1
191    }
192}
193
194impl TryFrom<&[u8]> for EntityStatus {
195    type Error = Error;
196    fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
197        let (data_len, mut offset) = utils::data_len_check(data, Self::length(), false)?;
198        let node_type = data[offset];
199        offset += 1;
200        let node_type = NodeType::from(node_type);
201        let mcts = data[offset];
202        offset += 1;
203        let ncts = data[offset];
204        offset += 1;
205        let max_data_size = match data_len - offset {
206            0 => Ok(None),
207            4 => Ok(Some(u32::from_be_bytes(
208                data[offset..offset + 4].try_into().unwrap(),
209            ))),
210            _ => Err(Error::InvalidLength {
211                actual: data_len,
212                expected: Self::length() + 4,
213            }),
214        }?;
215
216        Ok(Self {
217            node_type,
218            mcts,
219            ncts,
220            max_data_size,
221        })
222    }
223}
224
225impl From<EntityStatus> for Vec<u8> {
226    fn from(val: EntityStatus) -> Self {
227        let mut result = UDP_RESP_ENTITY_STATUS.to_be_bytes().to_vec();
228        let mut length = EntityStatus::length() as u32;
229        if val.max_data_size.is_some() {
230            length += 4;
231        }
232        result.extend(length.to_be_bytes());
233        result.push(val.node_type.into());
234        result.push(val.mcts);
235        result.push(val.ncts);
236        if let Some(size) = val.max_data_size {
237            result.extend(size.to_be_bytes());
238        }
239
240        result
241    }
242}
243
244impl Display for EntityStatus {
245    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
246        f.debug_struct("DoIP Entity Status")
247            .field("\n              Node Type", &self.node_type)
248            .field("\n    Max. TCP Connectors", &self.mcts)
249            .field("\n Current TCP Connectors", &self.ncts)
250            .field("\n       Max. Data Length", &self.max_data_size)
251            .finish()
252    }
253}
254
255#[derive(Debug, Clone, Eq, PartialEq, CopyGetters)]
256#[get_copy = "pub"]
257pub struct DiagnosticPowerMode {
258    // 0x4004
259    pub(crate) mode: PowerMode,
260}
261
262impl DiagnosticPowerMode {
263    pub fn new(mode: PowerMode) -> Self {
264        Self { mode }
265    }
266
267    #[inline]
268    const fn length() -> usize {
269        1
270    }
271}
272
273impl TryFrom<&[u8]> for DiagnosticPowerMode {
274    type Error = Error;
275    fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
276        let (_, offset) = utils::data_len_check(data, Self::length(), true)?;
277        let mode = data[offset];
278        let mode = PowerMode::from(mode);
279        Ok(Self { mode })
280    }
281}
282
283impl From<DiagnosticPowerMode> for Vec<u8> {
284    fn from(val: DiagnosticPowerMode) -> Self {
285        let mut result = UDP_RESP_DIAGNOSTIC_POWER_MODE.to_be_bytes().to_vec();
286        let length = DiagnosticPowerMode::length() as u32;
287        result.extend(length.to_be_bytes());
288        result.push(val.mode.into());
289        result
290    }
291}
292/****** --- end of UDP --- ********/
293
294/****** --- TCP --- ********/
295#[derive(Debug, Clone, Eq, PartialEq, CopyGetters)]
296#[get_copy = "pub"]
297pub struct RoutingActive {
298    // 0x0006
299    pub(crate) dst_addr: LogicAddress,
300    pub(crate) src_addr: LogicAddress,
301    pub(crate) active_code: ActiveCode,
302    pub(crate) reserved: u32,
303    // #[getter(name = "user_define")]
304    pub(crate) user_def: Option<u32>,
305}
306
307impl RoutingActive {
308    pub fn new(
309        dst_addr: LogicAddress,
310        src_addr: LogicAddress,
311        active_code: ActiveCode,
312        user_def: Option<u32>,
313    ) -> Self {
314        Self {
315            dst_addr,
316            src_addr,
317            active_code,
318            reserved: Default::default(),
319            user_def,
320        }
321    }
322
323    /// min length
324    #[inline]
325    const fn length() -> usize {
326        SIZE_OF_ADDRESS + SIZE_OF_ADDRESS + 1 + 4
327    }
328}
329
330impl TryFrom<&[u8]> for RoutingActive {
331    type Error = Error;
332    fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
333        let (data_len, mut offset) = utils::data_len_check(data, Self::length(), false)?;
334        let dst_addr =
335            u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
336        offset += SIZE_OF_ADDRESS;
337        let dst_addr = LogicAddress::from(dst_addr);
338        let src_addr =
339            u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
340        offset += SIZE_OF_ADDRESS;
341        let src_addr = LogicAddress::from(src_addr);
342        let active = data[offset];
343        offset += 1;
344        let active_code = ActiveCode::from(active);
345        let reserved = u32::from_be_bytes(data[offset..offset + 4].try_into().unwrap());
346        offset += 4;
347        let user_def = match data_len - offset {
348            0 => Ok(None),
349            4 => Ok(Some(u32::from_be_bytes(
350                data[offset..offset + 4].try_into().unwrap(),
351            ))),
352            _ => Err(Error::InvalidLength {
353                actual: data_len,
354                expected: Self::length() + 4,
355            }),
356        }?;
357
358        Ok(Self {
359            dst_addr,
360            src_addr,
361            active_code,
362            reserved,
363            user_def,
364        })
365    }
366}
367
368impl From<RoutingActive> for Vec<u8> {
369    fn from(val: RoutingActive) -> Self {
370        let mut result = TCP_RESP_ROUTING_ACTIVE.to_be_bytes().to_vec();
371        let mut length = RoutingActive::length() as u32;
372        if val.user_def.is_some() {
373            length += 4;
374        }
375        result.extend(length.to_be_bytes());
376        let dst_addr: u16 = val.dst_addr.into();
377        result.extend(dst_addr.to_be_bytes());
378        let src_addr: u16 = val.src_addr.into();
379        result.extend(src_addr.to_be_bytes());
380        result.push(val.active_code.into());
381        result.extend(val.reserved.to_be_bytes());
382        if let Some(user_def) = val.user_def {
383            result.extend(user_def.to_be_bytes());
384        }
385
386        result
387    }
388}
389
390#[derive(Debug, Clone, Eq, PartialEq, CopyGetters)]
391#[get_copy = "pub"]
392pub struct AliveCheck {
393    // 0x0008
394    pub(crate) src_addr: LogicAddress,
395}
396
397impl AliveCheck {
398    pub fn new(addr: LogicAddress) -> Self {
399        Self { src_addr: addr }
400    }
401
402    #[inline]
403    const fn length() -> usize {
404        SIZE_OF_ADDRESS
405    }
406}
407
408impl TryFrom<&[u8]> for AliveCheck {
409    type Error = Error;
410    fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
411        let (_, offset) = utils::data_len_check(data, Self::length(), true)?;
412        let src_addr = u16::from_be_bytes(data[offset..].try_into().unwrap());
413        let src_addr = LogicAddress::from(src_addr);
414
415        Ok(Self { src_addr })
416    }
417}
418
419impl From<AliveCheck> for Vec<u8> {
420    fn from(val: AliveCheck) -> Self {
421        let mut result = TCP_RESP_ALIVE_CHECK.to_be_bytes().to_vec();
422        let length = AliveCheck::length() as u32;
423        result.extend(length.to_be_bytes());
424        let src_addr: u16 = val.src_addr.into();
425        result.extend(src_addr.to_be_bytes());
426        result
427    }
428}
429
430#[derive(Debug, Clone, Eq, PartialEq, Getters)]
431#[get = "pub"]
432pub struct DiagnosticPositive {
433    // 0x8002
434    #[getset(get_copy = "pub")]
435    pub(crate) src_addr: LogicAddress,
436    #[getset(get_copy = "pub")]
437    pub(crate) dst_addr: LogicAddress,
438    #[getset(get_copy = "pub")]
439    pub(crate) code: DiagnosticPositiveCode,
440    // #[getter(name = "previous_diagnostic_data")]
441    #[getset(get = "pub")]
442    pub(crate) pre_diag_data: Vec<u8>,
443}
444
445impl DiagnosticPositive {
446    pub fn new(
447        src_addr: LogicAddress,
448        dst_addr: LogicAddress,
449        code: DiagnosticPositiveCode,
450        pre_diag_data: Vec<u8>,
451    ) -> Self {
452        if code != DiagnosticPositiveCode::Confirm {
453            rsutil::warn!("Diagnostic Positive code: {:?}", code);
454        }
455        Self {
456            src_addr,
457            dst_addr,
458            code,
459            pre_diag_data,
460        }
461    }
462    /// min length
463    #[inline]
464    const fn length() -> usize {
465        SIZE_OF_ADDRESS + SIZE_OF_ADDRESS + 1
466    }
467}
468
469impl TryFrom<&[u8]> for DiagnosticPositive {
470    type Error = Error;
471    fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
472        let (_, mut offset) = utils::data_len_check(data, Self::length(), false)?;
473        let src_addr =
474            u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
475        offset += SIZE_OF_ADDRESS;
476        let src_addr = LogicAddress::from(src_addr);
477        let dst_addr =
478            u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
479        offset += SIZE_OF_ADDRESS;
480        let dst_addr = LogicAddress::from(dst_addr);
481        let code = DiagnosticPositiveCode::from(data[offset]);
482        offset += 1;
483        let pre_diag_msg = data[offset..].to_vec();
484
485        Ok(Self::new(src_addr, dst_addr, code, pre_diag_msg))
486    }
487}
488
489impl From<DiagnosticPositive> for Vec<u8> {
490    fn from(mut val: DiagnosticPositive) -> Self {
491        let mut result = TCP_RESP_DIAGNOSTIC_POSITIVE.to_be_bytes().to_vec();
492        let length = (DiagnosticPositive::length() + val.pre_diag_data.len()) as u32;
493        result.extend(length.to_be_bytes());
494        let src_addr: u16 = val.src_addr.into();
495        result.extend(src_addr.to_be_bytes());
496        let dst_addr: u16 = val.dst_addr.into();
497        result.extend(dst_addr.to_be_bytes());
498        result.push(val.code.into());
499        result.append(&mut val.pre_diag_data);
500
501        result
502    }
503}
504
505impl Display for DiagnosticPositive {
506    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
507        f.debug_struct("Diagnostic Positive")
508            .field("\n       Source Address", &self.src_addr)
509            .field("\n       Target Address", &self.dst_addr)
510            .field("\n                 Code", &self.code)
511            .field("\n        Previous Data", &hex::encode(&self.pre_diag_data))
512            .finish()
513    }
514}
515
516#[derive(Debug, Clone, Eq, PartialEq, Getters, CopyGetters)]
517pub struct DiagnosticNegative {
518    // 0x8003
519    #[getset(get_copy = "pub")]
520    pub(crate) src_addr: LogicAddress,
521    #[getset(get_copy = "pub")]
522    pub(crate) dst_addr: LogicAddress,
523    #[getset(get_copy = "pub")]
524    pub(crate) code: DiagnosticNegativeCode,
525    // #[getter(name = "previous_diagnostic_data")]
526    #[getset(get = "pub")]
527    pub(crate) pre_diag_data: Vec<u8>,
528}
529
530impl DiagnosticNegative {
531    pub fn new(
532        src_addr: LogicAddress,
533        dst_addr: LogicAddress,
534        code: DiagnosticNegativeCode,
535        pre_diag_data: Vec<u8>,
536    ) -> Self {
537        Self {
538            src_addr,
539            dst_addr,
540            code,
541            pre_diag_data,
542        }
543    }
544
545    /// min length
546    #[inline]
547    const fn length() -> usize {
548        SIZE_OF_ADDRESS + SIZE_OF_ADDRESS + 1
549    }
550}
551
552impl TryFrom<&[u8]> for DiagnosticNegative {
553    type Error = Error;
554    fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
555        let (_, mut offset) = utils::data_len_check(data, Self::length(), false)?;
556        let src_addr =
557            u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
558        offset += SIZE_OF_ADDRESS;
559        let src_addr = LogicAddress::from(src_addr);
560        let dst_addr =
561            u16::from_be_bytes(data[offset..offset + SIZE_OF_ADDRESS].try_into().unwrap());
562        offset += SIZE_OF_ADDRESS;
563        let dst_addr = LogicAddress::from(dst_addr);
564        let code = DiagnosticNegativeCode::from(data[offset]);
565        offset += 1;
566        let pre_diag_data = data[offset..].to_vec();
567
568        Ok(Self {
569            src_addr,
570            dst_addr,
571            code,
572            pre_diag_data,
573        })
574    }
575}
576
577impl From<DiagnosticNegative> for Vec<u8> {
578    fn from(mut val: DiagnosticNegative) -> Self {
579        let mut result = TCP_RESP_DIAGNOSTIC_NEGATIVE.to_be_bytes().to_vec();
580        let length = (DiagnosticNegative::length() + val.pre_diag_data.len()) as u32;
581        result.extend(length.to_be_bytes());
582        let src_addr: u16 = val.src_addr.into();
583        result.extend(src_addr.to_be_bytes());
584        let dst_addr: u16 = val.dst_addr.into();
585        result.extend(dst_addr.to_be_bytes());
586        result.push(val.code.into());
587        result.append(&mut val.pre_diag_data);
588
589        result
590    }
591}
592
593impl Display for DiagnosticNegative {
594    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
595        f.debug_struct("Diagnostic Negative")
596            .field("\n       Source Address", &self.src_addr)
597            .field("\n       Target Address", &self.dst_addr)
598            .field("\n                 Code", &self.code)
599            .field("\n        Previous Data", &hex::encode(&self.pre_diag_data))
600            .finish()
601    }
602}
603/****** --- end of UDP --- ********/