someip_parse/
someip_header.rs

1use crate::*;
2
3/// Deprecated use [`SomeipHeader`] instead.
4#[deprecated(
5    since = "0.5.0",
6    note = "Use SomeipHeader instead (renamed, 'i' is lower case now)."
7)]
8pub type SomeIpHeader = SomeipHeader;
9
10///SOMEIP header (including tp header if present).
11#[derive(Clone, Debug, Eq, PartialEq)]
12pub struct SomeipHeader {
13    pub message_id: u32,
14    pub length: u32,
15    pub request_id: u32,
16    pub interface_version: u8,
17    ///Message type (does not contain the tp flag, this is determined if something is present in the tp_header field).
18    pub message_type: MessageType,
19    pub return_code: u8, //TODO replace with enum?
20    ///Contains a tp header (Transporting large SOME/IP messages of UDP [SOME/IP-TP]).
21    ///
22    ///If there is a tp header a someip payload is split over multiple messages and the tp header contains the
23    ///start offset of the payload of this message relative to the completly assembled payload.
24    pub tp_header: Option<TpHeader>,
25}
26
27impl SomeipHeader {
28    ///Create a service discovery message header.
29    pub fn new_sd_header(length: u32, session_id: u16, tp_header: Option<TpHeader>) -> Self {
30        Self {
31            message_id: SOMEIP_SD_MESSAGE_ID, // defined in spec
32            length,
33            request_id: session_id as u32, // client-id is 0x00
34            interface_version: 0x01,       // defined in spec
35            message_type: MessageType::Notification, // defined in spec
36            return_code: 0x00,             // defined in spec
37            tp_header,
38        }
39    }
40
41    ///Returns the service id (first 16 bits of the message id)
42    #[inline]
43    pub fn service_id(&self) -> u16 {
44        ((self.message_id & 0xffff_0000) >> 16) as u16
45    }
46
47    ///Set the servide id (first 16 bits of the message id)
48    #[inline]
49    pub fn set_service_id(&mut self, service_id: u16) {
50        self.message_id = (self.message_id & 0x0000_ffff) | (u32::from(service_id) << 16);
51    }
52
53    ///Set the event id + the event bit.
54    #[inline]
55    pub fn set_event_id(&mut self, event_id: u16) {
56        self.message_id = (self.message_id & 0xffff_0000) | u32::from(0x8000 | event_id);
57    }
58
59    ///Set the event id + the event bit to 0. Asserting method_id <= 0x7FFF (otherwise the )
60    #[inline]
61    pub fn set_method_id(&mut self, method_id: u16) {
62        debug_assert!(method_id <= 0x7FFF);
63        self.message_id = (self.message_id & 0xffff_0000) | u32::from(0x7fff & method_id);
64    }
65
66    ///Sets the event id or method id. This number mjust include the "event bit".
67    #[inline]
68    pub fn set_method_or_event_id(&mut self, method_id: u16) {
69        self.message_id = (self.message_id & 0xffff_0000) | u32::from(method_id);
70    }
71
72    ///Returns true if the message has the message id of a some ip service discovery message.
73    #[inline]
74    pub fn is_someip_sd(&self) -> bool {
75        SOMEIP_SD_MESSAGE_ID == self.message_id
76    }
77
78    ///Returns true if the event or notification bit in the message id is set
79    #[inline]
80    pub fn is_event(&self) -> bool {
81        0 != self.message_id & 0x8000
82    }
83
84    ///Return the event id or method id. This number includes the "event bit".
85    #[inline]
86    pub fn event_or_method_id(&self) -> u16 {
87        (self.message_id & 0x0000_ffff) as u16
88    }
89
90    ///Return the event id. `None` if event bit is not set.
91    #[inline]
92    pub fn event_id(&self) -> Option<u16> {
93        if self.is_event() {
94            Some(self.event_or_method_id() & 0x7fff)
95        } else {
96            None
97        }
98    }
99
100    ///Return the method id. `None` if event bit is set.
101    #[inline]
102    pub fn method_id(&self) -> Option<u16> {
103        if !self.is_event() {
104            Some(self.event_or_method_id() & 0x7fff)
105        } else {
106            None
107        }
108    }
109
110    ///Serialize the header.
111    pub fn write_raw<T: std::io::Write>(&self, writer: &mut T) -> Result<(), std::io::Error> {
112        writer.write_all(&self.base_to_bytes())?;
113        if let Some(ref tp) = self.tp_header {
114            tp.write(writer)?;
115        }
116        Ok(())
117    }
118
119    /// Returns the encoded SOMEIP header (without the TP header).
120    #[inline]
121    pub fn base_to_bytes(&self) -> [u8; SOMEIP_HEADER_LENGTH] {
122        let message_id_be = self.message_id.to_be_bytes();
123        let length_be = self.length.to_be_bytes();
124        let request_id_be = self.request_id.to_be_bytes();
125        [
126            message_id_be[0],
127            message_id_be[1],
128            message_id_be[2],
129            message_id_be[3],
130            length_be[0],
131            length_be[1],
132            length_be[2],
133            length_be[3],
134            request_id_be[0],
135            request_id_be[1],
136            request_id_be[2],
137            request_id_be[3],
138            SOMEIP_PROTOCOL_VERSION,
139            self.interface_version,
140            match self.tp_header {
141                Some(_) => (self.message_type.clone() as u8) | SOMEIP_HEADER_MESSAGE_TYPE_TP_FLAG,
142                None => self.message_type.clone() as u8,
143            },
144            self.return_code,
145        ]
146    }
147
148    ///Read a header from a byte stream.
149    pub fn read<T: std::io::Read>(
150        reader: &mut T,
151    ) -> Result<SomeipHeader, err::SomeipHeaderReadError> {
152        use err::{SomeipHeaderError::*, SomeipHeaderReadError::*};
153
154        // read the header
155        let mut header_bytes: [u8; SOMEIP_HEADER_LENGTH] = [0; SOMEIP_HEADER_LENGTH];
156        reader.read_exact(&mut header_bytes).map_err(Io)?;
157
158        // validate length
159        let length = u32::from_be_bytes([
160            header_bytes[4],
161            header_bytes[5],
162            header_bytes[6],
163            header_bytes[7],
164        ]);
165        if length < SOMEIP_LEN_OFFSET_TO_PAYLOAD {
166            return Err(Content(LengthFieldTooSmall(length)));
167        }
168
169        // validate protocol version
170        let protocol_version = header_bytes[12];
171        if SOMEIP_PROTOCOL_VERSION != protocol_version {
172            return Err(Content(UnsupportedProtocolVersion(protocol_version)));
173        }
174
175        // validate message type
176        let message_type_raw = header_bytes[14];
177        let message_type = {
178            use MessageType::*;
179            //check that message type is valid
180            match message_type_raw & !(SOMEIP_HEADER_MESSAGE_TYPE_TP_FLAG) {
181                0x0 => Request,
182                0x1 => RequestNoReturn,
183                0x2 => Notification,
184                0x80 => Response,
185                0x81 => Error,
186                _ => return Err(Content(UnknownMessageType(message_type_raw))),
187            }
188        };
189
190        Ok(SomeipHeader {
191            message_id: u32::from_be_bytes([
192                header_bytes[0],
193                header_bytes[1],
194                header_bytes[2],
195                header_bytes[3],
196            ]),
197            length,
198            request_id: u32::from_be_bytes([
199                header_bytes[8],
200                header_bytes[9],
201                header_bytes[10],
202                header_bytes[11],
203            ]),
204            interface_version: header_bytes[13],
205            message_type,
206            return_code: header_bytes[15],
207            //read the tp header if the flag is set
208            tp_header: if 0 != message_type_raw & SOMEIP_HEADER_MESSAGE_TYPE_TP_FLAG {
209                Some(TpHeader::read(reader).map_err(Io)?)
210            } else {
211                None
212            },
213        })
214    }
215}
216
217impl Default for SomeipHeader {
218    fn default() -> SomeipHeader {
219        SomeipHeader {
220            message_id: 0,
221            length: SOMEIP_LEN_OFFSET_TO_PAYLOAD,
222            request_id: 0,
223            interface_version: 0,
224            message_type: MessageType::Request,
225            return_code: 0,
226            tp_header: None,
227        }
228    }
229}
230
231#[cfg(test)]
232mod tests {
233    use super::proptest_generators::*;
234    use super::*;
235    use proptest::prelude::*;
236    use std::io::{Cursor, Write};
237    use MessageType::*;
238
239    const MESSAGE_TYPE_VALUES: &[MessageType; 5] =
240        &[Request, RequestNoReturn, Notification, Response, Error];
241
242    const MESSAGE_TYPE_VALUES_RAW: &[u8; 10] = &[
243        Request as u8,
244        RequestNoReturn as u8,
245        Notification as u8,
246        Response as u8,
247        Error as u8,
248        Request as u8 | SOMEIP_HEADER_MESSAGE_TYPE_TP_FLAG,
249        RequestNoReturn as u8 | SOMEIP_HEADER_MESSAGE_TYPE_TP_FLAG,
250        Notification as u8 | SOMEIP_HEADER_MESSAGE_TYPE_TP_FLAG,
251        Response as u8 | SOMEIP_HEADER_MESSAGE_TYPE_TP_FLAG,
252        Error as u8 | SOMEIP_HEADER_MESSAGE_TYPE_TP_FLAG,
253    ];
254
255    #[test]
256    fn default() {
257        let header: SomeipHeader = Default::default();
258        assert_eq!(0, header.message_id);
259        assert_eq!(SOMEIP_LEN_OFFSET_TO_PAYLOAD, header.length);
260        assert_eq!(0, header.request_id);
261        assert_eq!(0, header.interface_version);
262        assert_eq!(MessageType::Request, header.message_type);
263        assert_eq!(None, header.tp_header);
264        assert_eq!(0, header.return_code);
265    }
266
267    proptest! {
268        #[test]
269        fn write_read(ref input_base in someip_header_any()) {
270            for message_type in MESSAGE_TYPE_VALUES {
271                let input = {
272                    let mut value = input_base.clone();
273                    value.message_type = message_type.clone();
274                    value
275                };
276                let mut buffer = Vec::new();
277                input.write_raw(&mut buffer).unwrap();
278
279                //read the header
280                let mut cursor = Cursor::new(&buffer);
281                let result = SomeipHeader::read(&mut cursor).unwrap();
282                assert_eq!(input, result);
283
284                //check that a too smal cursor results in an io error
285                {
286                    let buffer_len = buffer.len();
287                    assert!(SomeipHeader::read(&mut Cursor::new(&buffer[..buffer_len-1])).unwrap_err().io_error().is_some());
288                }
289            }
290        }
291    }
292
293    proptest! {
294        #[test]
295        fn from_slice(length in SOMEIP_LEN_OFFSET_TO_PAYLOAD..1234,
296                      ref input_base in someip_header_any(),
297                      add in 0usize..15) {
298            for message_type in MESSAGE_TYPE_VALUES {
299                //calculate the length based on if there tp header is present
300                let length = if input_base.tp_header.is_some() {
301                    length + TP_HEADER_LENGTH as u32
302                } else {
303                    length
304                };
305
306                let input = {
307                    let mut value = input_base.clone();
308                    value.length = length;
309                    value.message_type = message_type.clone();
310                    value
311                };
312
313                let mut buffer = Vec::new();
314                input.write_raw(&mut buffer).unwrap();
315
316                //add some payload
317                let expected_length =
318                    length as usize
319                    + (SOMEIP_HEADER_LENGTH - SOMEIP_LEN_OFFSET_TO_PAYLOAD as usize);
320                buffer.resize(expected_length + add, 0);
321
322                //from_slice
323                let slice = SomeipMsgSlice::from_slice(&buffer[..]).unwrap();
324                assert_eq!(input.message_id, slice.message_id());
325                assert_eq!(input.length, slice.length());
326                assert_eq!(input.request_id, slice.request_id());
327                assert_eq!(SOMEIP_PROTOCOL_VERSION, slice.protocol_version());
328                assert_eq!(input.interface_version, slice.interface_version());
329                assert_eq!(input.message_type, slice.message_type());
330                assert_eq!(input.tp_header, slice.tp_header());
331                assert_eq!(input.tp_header.is_some(), slice.is_tp());
332                assert_eq!(input.return_code, slice.return_code());
333                assert_eq!(&buffer[(
334                    if input.tp_header.is_some() {
335                        SOMEIP_HEADER_LENGTH + TP_HEADER_LENGTH
336                    } else {
337                        SOMEIP_HEADER_LENGTH
338                    }
339                )..expected_length], slice.payload());
340
341                //internal slice checking
342                assert_eq!(&buffer[..expected_length], slice.slice());
343
344                //to_header
345                assert_eq!(input, slice.to_header());
346
347                //check that a too small slice triggers an error
348                use err::{*, SomeipSliceError::*};
349                assert_eq!(
350                    SomeipMsgSlice::from_slice(&buffer[..expected_length-1]),
351                    Err(Len(LenError {
352                        required_len: expected_length,
353                        len: expected_length - 1,
354                        len_source: if expected_length <= SOMEIP_HEADER_LENGTH {
355                            LenSource::Slice
356                        } else {
357                            LenSource::SomeipHeaderLength
358                        },
359                        layer: if expected_length <= SOMEIP_HEADER_LENGTH {
360                            Layer::SomeipHeader
361                        } else {
362                            Layer::SomeipPayload
363                        },
364                    }))
365                );
366            }
367        }
368    }
369
370    proptest! {
371        #[test]
372        fn unknown_message_type(length in SOMEIP_LEN_OFFSET_TO_PAYLOAD..1234,
373                                ref input_base in someip_header_any(),
374                                message_type in any::<u8>().prop_filter("message type must be unknown",
375                               |v| !MESSAGE_TYPE_VALUES_RAW.iter().any(|&x| (v == &x ||
376                                                                             (SOMEIP_HEADER_MESSAGE_TYPE_TP_FLAG | v) == x)))
377            )
378        {
379            //add the tp header length in case the tp flag is set
380            let length = if 0 != (SOMEIP_HEADER_MESSAGE_TYPE_TP_FLAG & message_type) {
381                length + 4
382            } else {
383                length
384            };
385
386            let input = {
387                let mut value = input_base.clone();
388                value.length = length;
389                value
390            };
391
392            //serialize to buffer
393            let mut buffer = Vec::new();
394            input.write_raw(&mut buffer).unwrap();
395
396            //add some payload
397            let expected_length = length as usize + (SOMEIP_HEADER_LENGTH - SOMEIP_LEN_OFFSET_TO_PAYLOAD as usize);
398            buffer.resize(expected_length, 0);
399
400            //insert the invalid message type
401            buffer[14] = message_type;
402
403            //check that deserialization triggers an error
404            use err::{SomeipSliceError::*, SomeipHeaderError::*};
405            assert_eq!(
406                SomeipHeader::read(&mut Cursor::new(&buffer)).unwrap_err().content_error(),
407                Some(UnknownMessageType(message_type))
408            );
409            assert_eq!(
410                SomeipMsgSlice::from_slice(&buffer),
411                Err(Content(UnknownMessageType(message_type)))
412            );
413        }
414    }
415
416    #[test]
417    fn read_unsupported_protocol_version() {
418        let mut buffer = Vec::new();
419        SomeipHeader::default().write_raw(&mut buffer).unwrap();
420        //set the protocol to an unsupported version
421        buffer[4 * 3] = 0;
422        let mut cursor = Cursor::new(&buffer);
423        let result = SomeipHeader::read(&mut cursor);
424        use err::{SomeipHeaderError::*, SomeipSliceError::*};
425        assert_eq!(
426            result.unwrap_err().content_error(),
427            Some(UnsupportedProtocolVersion(0))
428        );
429        assert_eq!(
430            SomeipMsgSlice::from_slice(&buffer[..]),
431            Err(Content(UnsupportedProtocolVersion(0)))
432        );
433    }
434
435    #[test]
436    fn read_too_small_length_field() {
437        //0
438        {
439            let mut buffer = Vec::new();
440            SomeipHeader::default().write_raw(&mut buffer).unwrap();
441            //set the length to 0
442            {
443                buffer[4] = 0;
444                buffer[5] = 0;
445                buffer[6] = 0;
446                buffer[7] = 0;
447            }
448            let mut cursor = Cursor::new(&buffer);
449            let result = SomeipHeader::read(&mut cursor);
450            use err::{SomeipHeaderError::*, SomeipSliceError::*};
451            assert_eq!(
452                result.unwrap_err().content_error(),
453                Some(LengthFieldTooSmall(0))
454            );
455            //check the from_slice method
456            assert_eq!(
457                SomeipMsgSlice::from_slice(&buffer[..]),
458                Err(Content(LengthFieldTooSmall(0)))
459            );
460        }
461        //SOMEIP_LEN_OFFSET_TO_PAYLOAD - 1
462        {
463            let mut buffer = Vec::new();
464            SomeipHeader::default().write_raw(&mut buffer).unwrap();
465            //set the length to SOMEIP_LEN_OFFSET_TO_PAYLOAD - 1
466            const TOO_SMALL: u32 = SOMEIP_LEN_OFFSET_TO_PAYLOAD - 1;
467            {
468                let length_be = TOO_SMALL.to_be_bytes();
469                buffer[4] = length_be[0];
470                buffer[5] = length_be[1];
471                buffer[6] = length_be[2];
472                buffer[7] = length_be[3];
473            }
474            let mut cursor = Cursor::new(&buffer);
475            let result = SomeipHeader::read(&mut cursor);
476            use err::{SomeipHeaderError::*, SomeipSliceError::*};
477            assert_eq!(
478                result.unwrap_err().content_error(),
479                Some(LengthFieldTooSmall(TOO_SMALL))
480            );
481            assert_eq!(
482                SomeipMsgSlice::from_slice(&buffer[..]),
483                Err(Content(LengthFieldTooSmall(TOO_SMALL)))
484            );
485        }
486    }
487
488    proptest! {
489        #[test]
490        fn service_id(packet in someip_header_with_payload_any(),
491                      service_id in 0x0u16..std::u16::MAX)
492        {
493            let mut header = packet.0.clone();
494            header.set_service_id(service_id);
495            assert_eq!(service_id, header.service_id());
496
497            //serialize and check the slice methods
498            let mut buffer = Vec::new();
499            header.write_raw(&mut buffer).unwrap();
500            buffer.write(&packet.1[..]).unwrap();
501            let slice = SomeipMsgSlice::from_slice(&buffer[..]).unwrap();
502
503            assert_eq!(service_id, slice.service_id());
504        }
505    }
506
507    proptest! {
508        #[test]
509        fn set_get_method_id(packet in someip_header_with_payload_any(),
510                             method_id in 0u16..0x7fff)
511        {
512            let mut header = packet.0.clone();
513            header.set_method_id(method_id);
514
515            assert_eq!(method_id, header.event_or_method_id());
516            assert_eq!(Some(method_id), header.method_id());
517            assert_eq!(false, header.is_event());
518            assert_eq!(None, header.event_id());
519
520            //serialize and check the slice methods
521            let mut buffer = Vec::new();
522            header.write_raw(&mut buffer).unwrap();
523            buffer.write(&packet.1[..]).unwrap();
524            let slice = SomeipMsgSlice::from_slice(&buffer[..]).unwrap();
525
526            assert_eq!(false, slice.is_event());
527            assert_eq!(Some(method_id), slice.method_id());
528            assert_eq!(method_id, slice.event_or_method_id());
529            assert_eq!(None, slice.event_id());
530        }
531    }
532
533    proptest! {
534        #[test]
535        fn set_get_event_id(packet in someip_header_with_payload_any(),
536                            event_id in 0u16..0x7fff)
537        {
538            let mut header = packet.0.clone();
539            header.set_event_id(event_id);
540
541            let id_with_bit = event_id | 0x8000;
542
543            assert_eq!(id_with_bit, header.event_or_method_id());
544            assert_eq!(Some(event_id), header.event_id());
545            assert_eq!(true, header.is_event());
546            assert_eq!(None, header.method_id());
547
548            //serialize and check the slice methods
549            let mut buffer = Vec::new();
550            header.write_raw(&mut buffer).unwrap();
551            buffer.write(&packet.1[..]).unwrap();
552            let slice = SomeipMsgSlice::from_slice(&buffer[..]).unwrap();
553
554            assert_eq!(true, slice.is_event());
555            assert_eq!(id_with_bit, slice.event_or_method_id());
556            assert_eq!(Some(event_id), slice.event_id());
557            assert_eq!(None, slice.method_id());
558        }
559    }
560
561    proptest! {
562        #[test]
563        fn set_method_or_event_id(packet in someip_header_with_payload_any(),
564                                  id in 0x0u16..std::u16::MAX)
565        {
566            let mut header = packet.0.clone();
567            header.set_method_or_event_id(id);
568
569            assert_eq!(id, header.event_or_method_id());
570            assert_eq!(id >= 0x8000, header.is_event());
571
572            //serialize and check the slice methods
573            let mut buffer = Vec::new();
574            header.write_raw(&mut buffer).unwrap();
575            buffer.write(&packet.1[..]).unwrap();
576            let slice = SomeipMsgSlice::from_slice(&buffer[..]).unwrap();
577
578            assert_eq!(id >= 0x8000, slice.is_event());
579            assert_eq!(id, slice.event_or_method_id());
580        }
581    }
582
583    proptest! {
584        #[test]
585        fn is_someip_sd(packet in someip_header_with_payload_any())
586        {
587            const SD_MESSAGE_ID: u32 = 0xFFFF8100;
588
589            let mut header = packet.0.clone();
590            header.message_id = SD_MESSAGE_ID;
591
592            assert_eq!(true, header.is_someip_sd());
593            assert_eq!(packet.0.message_id == SD_MESSAGE_ID, packet.0.is_someip_sd());
594
595            //serialize and check the slice methods
596            //some ip sd packet
597            {
598                let mut buffer = Vec::new();
599                header.write_raw(&mut buffer).unwrap();
600                buffer.write(&packet.1[..]).unwrap();
601                let slice = SomeipMsgSlice::from_slice(&buffer[..]).unwrap();
602
603                assert_eq!(true, slice.is_someip_sd());
604            }
605            //random packet
606            {
607                let mut buffer = Vec::new();
608                packet.0.write_raw(&mut buffer).unwrap();
609                buffer.write(&packet.1[..]).unwrap();
610                let slice = SomeipMsgSlice::from_slice(&buffer[..]).unwrap();
611
612                assert_eq!(packet.0.message_id == SD_MESSAGE_ID, slice.is_someip_sd());
613            }
614        }
615    }
616}