Skip to main content

c_its_parser/transport/
mod.rs

1//! GeoNetworking Transport Layer Parser
2
3use alloc::string::ToString;
4use core::fmt::Debug;
5
6#[cfg(feature = "json")]
7use serde::{Deserialize, Serialize};
8
9use crate::map_err_to_string;
10
11pub(crate) mod decode;
12pub(crate) mod encode;
13
14#[derive(Debug, Clone, PartialEq)]
15/// GeoNetworking "next header" of the Common Header
16pub enum TransportHeader {
17    /// Transport protocol (BTP-A for interactive packet transport) as defined in ETSI EN 302 636-5-1
18    BtpA(BasicTransportAHeader),
19    /// Transport protocol (BTP-B for non-interactive packet transport) as defined in ETSI EN 302 636-5-1
20    BtpB(BasicTransportBHeader),
21    /// IPv6 header as defined in ETSI EN 302 636-6-1
22    IPv6(alloc::boxed::Box<IPv6Header>),
23}
24
25impl TransportHeader {
26    /// Decodes a GeoNetworking Transport Header from binary buffer
27    ///
28    /// The "next header" type needs to be supplied in `next_header`.
29    /// Returns the remaining data after the transport header.
30    ///
31    /// # Errors
32    /// Returns a human-readable error when parsing failed of unsupported header type was selected.
33    pub fn decode_with_gn_next_header(
34        next_header: geonetworking::en302636_4_1::NextAfterCommon,
35        bytes: &[u8],
36    ) -> Result<(&[u8], TransportHeader), alloc::string::String> {
37        use decode::Decode as _;
38
39        match next_header {
40            geonetworking::en302636_4_1::NextAfterCommon::Any => {
41                Err("Currently, only BTP and IPv6 Headers can be decoded!".to_string())
42            }
43            geonetworking::en302636_4_1::NextAfterCommon::BTPA => {
44                BasicTransportAHeader::decode(bytes)
45                    .map(|(rem, btpa)| (rem, TransportHeader::BtpA(btpa)))
46                    .map_err(map_err_to_string)
47            }
48            geonetworking::en302636_4_1::NextAfterCommon::BTPB => {
49                BasicTransportBHeader::decode(bytes)
50                    .map(|(rem, btpb)| (rem, TransportHeader::BtpB(btpb)))
51                    .map_err(map_err_to_string)
52            }
53            geonetworking::en302636_4_1::NextAfterCommon::IPv6 => IPv6Header::decode(bytes)
54                .map(|(rem, ipv6)| (rem, TransportHeader::IPv6(alloc::boxed::Box::new(ipv6))))
55                .map_err(map_err_to_string),
56        }
57    }
58
59    /// Encodes a GeoNetworking Transport Header returning the binary buffer
60    ///
61    /// Note: Encoding IPv6 headers is not supported.
62    ///
63    /// # Errors
64    /// Returns a human-readable error when encoding failed.
65    pub fn encode(&self) -> Result<alloc::vec::Vec<u8>, alloc::string::String> {
66        use encode::Encode as _;
67
68        match self {
69            TransportHeader::BtpA(a) => a.encode().map_err(map_err_to_string),
70            TransportHeader::BtpB(b) => b.encode().map_err(map_err_to_string),
71            TransportHeader::IPv6(_) => Err(alloc::string::String::from(
72                "Encoding IPv6 headers is unsupported!",
73            )),
74        }
75    }
76
77    #[cfg(feature = "json")]
78    /// Encodes a GeoNetworking Transport Header as a JSON representation
79    ///
80    /// Note: Encoding IPv6 headers is not supported.
81    ///
82    /// # Errors
83    /// Returns a human-readable error when encoding failed.
84    pub fn encode_to_json(&self) -> Result<alloc::string::String, alloc::string::String> {
85        match self {
86            TransportHeader::BtpA(a) => a.encode_to_json().map_err(map_err_to_string),
87            TransportHeader::BtpB(b) => b.encode_to_json().map_err(map_err_to_string),
88            TransportHeader::IPv6(_) => Err(alloc::string::String::from(
89                "Encoding IPv6 headers is unsupported!",
90            )),
91        }
92    }
93}
94
95#[derive(Debug, Clone, PartialEq)]
96#[cfg_attr(feature = "json", derive(Serialize, Deserialize))]
97/// An ETSI EN 302 636-5-1 BTP-A header
98pub struct BasicTransportAHeader {
99    /// identifies the protocol entity at the destination's ITS facilities layer
100    pub destination_port: u16,
101    /// identifies the protocol entity at the source's ITS facilities layer
102    pub source_port: u16,
103}
104
105#[derive(Debug, Clone, PartialEq)]
106#[cfg_attr(feature = "json", derive(Serialize, Deserialize))]
107/// An ETSI EN 302 636-5-1 BTP-B header
108pub struct BasicTransportBHeader {
109    /// It identifies the protocol entity at the ITS facilities layer in the destination.
110    /// For well-known ports it shall be set to a value corresponding to the
111    /// identified facilities layer service as specified the values in ETSI TS 103 248
112    pub destination_port: u16,
113    /// It provides additional information. If Destination port is a well-known port
114    /// and the field value is specified in ETSI TS 103 248, it shall be set to a value
115    /// corresponding to the identified facilities layer service as specified in ETSI TS 103 248.
116    /// Default setting is 0
117    pub destination_port_info: u16,
118}
119
120#[derive(Debug, Clone, PartialEq)]
121/// An ETSI EN 302 636-6-1 IPv6 header
122pub struct IPv6Header {
123    pub ip: Option<etherparse::NetHeaders>,
124    pub link: Option<etherparse::LinkHeader>,
125    pub transport: Option<etherparse::TransportHeader>,
126    // note: etherparse supports multiple link header extensions, but we assume 1 or none
127    pub link_ext: Option<etherparse::LinkExtHeader>,
128}