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