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::NextAfterCommon,
35        bytes: &[u8],
36    ) -> Result<(&[u8], TransportHeader), alloc::string::String> {
37        use decode::Decode as _;
38
39        match next_header {
40            geonetworking::NextAfterCommon::Any => {
41                Err("Currently, only BTP and IPv6 Headers can be decoded!".to_string())
42            }
43            geonetworking::NextAfterCommon::BTPA => BasicTransportAHeader::decode(bytes)
44                .map(|(rem, btpa)| (rem, TransportHeader::BtpA(btpa)))
45                .map_err(map_err_to_string),
46            geonetworking::NextAfterCommon::BTPB => BasicTransportBHeader::decode(bytes)
47                .map(|(rem, btpb)| (rem, TransportHeader::BtpB(btpb)))
48                .map_err(map_err_to_string),
49            geonetworking::NextAfterCommon::IPv6 => IPv6Header::decode(bytes)
50                .map(|(rem, ipv6)| (rem, TransportHeader::IPv6(alloc::boxed::Box::new(ipv6))))
51                .map_err(map_err_to_string),
52        }
53    }
54
55    /// Encodes a GeoNetworking Transport Header returning the binary buffer
56    ///
57    /// Note: Encoding IPv6 headers is not supported.
58    ///
59    /// # Errors
60    /// Returns a human-readable error when encoding failed.
61    pub fn encode(&self) -> Result<alloc::vec::Vec<u8>, alloc::string::String> {
62        use encode::Encode as _;
63
64        match self {
65            TransportHeader::BtpA(a) => a.encode().map_err(map_err_to_string),
66            TransportHeader::BtpB(b) => b.encode().map_err(map_err_to_string),
67            TransportHeader::IPv6(_) => Err(alloc::string::String::from(
68                "Encoding IPv6 headers is unsupported!",
69            )),
70        }
71    }
72
73    #[cfg(feature = "json")]
74    /// Encodes a GeoNetworking Transport Header as a JSON representation
75    ///
76    /// Note: Encoding IPv6 headers is not supported.
77    ///
78    /// # Errors
79    /// Returns a human-readable error when encoding failed.
80    pub fn encode_to_json(&self) -> Result<alloc::string::String, alloc::string::String> {
81        match self {
82            TransportHeader::BtpA(a) => a.encode_to_json().map_err(map_err_to_string),
83            TransportHeader::BtpB(b) => b.encode_to_json().map_err(map_err_to_string),
84            TransportHeader::IPv6(_) => Err(alloc::string::String::from(
85                "Encoding IPv6 headers is unsupported!",
86            )),
87        }
88    }
89}
90
91#[derive(Debug, Clone, PartialEq)]
92#[cfg_attr(feature = "json", derive(Serialize, Deserialize))]
93/// An ETSI EN 302 636-5-1 BTP-A header
94pub struct BasicTransportAHeader {
95    /// identifies the protocol entity at the destination's ITS facilities layer
96    pub destination_port: u16,
97    /// identifies the protocol entity at the source's ITS facilities layer
98    pub source_port: u16,
99}
100
101#[derive(Debug, Clone, PartialEq)]
102#[cfg_attr(feature = "json", derive(Serialize, Deserialize))]
103/// An ETSI EN 302 636-5-1 BTP-B header
104pub struct BasicTransportBHeader {
105    /// It identifies the protocol entity at the ITS facilities layer in the destination.
106    /// For well-known ports it shall be set to a value corresponding to the
107    /// identified facilities layer service as specified the values in ETSI TS 103 248
108    pub destination_port: u16,
109    /// It provides additional information. If Destination port is a well-known port
110    /// and the field value is specified in ETSI TS 103 248, it shall be set to a value
111    /// corresponding to the identified facilities layer service as specified in ETSI TS 103 248.
112    /// Default setting is 0
113    pub destination_port_info: u16,
114}
115
116#[derive(Debug, Clone, PartialEq)]
117/// An ETSI EN 302 636-6-1 IPv6 header
118pub struct IPv6Header {
119    pub ip: Option<etherparse::NetHeaders>,
120    pub link: Option<etherparse::LinkHeader>,
121    pub transport: Option<etherparse::TransportHeader>,
122    // note: etherparse supports multiple link header extensions, but we assume 1 or none
123    pub link_ext: Option<etherparse::LinkExtHeader>,
124}