Skip to main content

simple_someip/protocol/sd/
options.rs

1use std::net::Ipv4Addr;
2
3use crate::protocol::{
4    Error,
5    byte_order::{ReadBytesExt, WriteBytesExt},
6};
7
8#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
9pub enum TransportProtocol {
10    Udp,
11    Tcp,
12}
13
14impl TryFrom<u8> for TransportProtocol {
15    type Error = Error;
16    fn try_from(value: u8) -> Result<Self, Error> {
17        match value {
18            0x11 => Ok(TransportProtocol::Udp),
19            0x06 => Ok(TransportProtocol::Tcp),
20            _ => Err(Error::InvalidSDOptionTransportProtocol(value)),
21        }
22    }
23}
24
25impl From<TransportProtocol> for u8 {
26    fn from(transport_protocol: TransportProtocol) -> u8 {
27        match transport_protocol {
28            TransportProtocol::Udp => 0x11,
29            TransportProtocol::Tcp => 0x06,
30        }
31    }
32}
33
34enum OptionType {
35    Configuration,
36    LoadBalancing,
37    IpV4Endpoint,
38    IpV6Endpoint,
39    IpV4Multicast,
40    IpV6Multicast,
41    IpV4SD,
42    IpV6SD,
43}
44
45impl TryFrom<u8> for OptionType {
46    type Error = Error;
47    fn try_from(value: u8) -> Result<Self, Error> {
48        match value {
49            0x01 => Ok(OptionType::Configuration),
50            0x02 => Ok(OptionType::LoadBalancing),
51            0x04 => Ok(OptionType::IpV4Endpoint),
52            0x06 => Ok(OptionType::IpV6Endpoint),
53            0x14 => Ok(OptionType::IpV4Multicast),
54            0x16 => Ok(OptionType::IpV6Multicast),
55            0x24 => Ok(OptionType::IpV4SD),
56            0x26 => Ok(OptionType::IpV6SD),
57            _ => Err(Error::InvalidSDOptionType(value)),
58        }
59    }
60}
61
62impl From<OptionType> for u8 {
63    fn from(option_type: OptionType) -> u8 {
64        match option_type {
65            OptionType::Configuration => 0x01,
66            OptionType::LoadBalancing => 0x02,
67            OptionType::IpV4Endpoint => 0x04,
68            OptionType::IpV6Endpoint => 0x06,
69            OptionType::IpV4Multicast => 0x14,
70            OptionType::IpV6Multicast => 0x16,
71            OptionType::IpV4SD => 0x24,
72            OptionType::IpV6SD => 0x26,
73        }
74    }
75}
76
77#[derive(Clone, Debug, Eq, PartialEq)]
78pub enum Options {
79    Configuration,
80    LoadBalancing,
81    IpV4Endpoint {
82        ip: Ipv4Addr,
83        protocol: TransportProtocol,
84        port: u16,
85    },
86    IpV6Endpoint,
87    IpV4Multicast,
88    IpV6Multicast,
89    IpV4SD,
90    IpV6SD,
91}
92
93impl Options {
94    #[must_use]
95    pub fn size(&self) -> usize {
96        match self {
97            Options::Configuration => todo!("Options::Configuration not implemented"),
98            Options::LoadBalancing => todo!("Options::Configuration not implemented"),
99            Options::IpV4Endpoint { .. } => 12,
100            Options::IpV6Endpoint => todo!("Options::Configuration not implemented"),
101            Options::IpV4Multicast => todo!("Options::Configuration not implemented"),
102            Options::IpV6Multicast => todo!("Options::Configuration not implemented"),
103            Options::IpV4SD => todo!("Options::Configuration not implemented"),
104            Options::IpV6SD => todo!("Options::Configuration not implemented"),
105        }
106    }
107
108    pub fn write<T: embedded_io::Write>(&self, writer: &mut T) -> Result<usize, Error> {
109        writer.write_u16_be(u16::try_from(self.size() - 3).expect("option size fits u16"))?;
110        match self {
111            Options::Configuration => todo!("Options::Configuration not implemented"),
112            Options::LoadBalancing => todo!("Options::Configuration not implemented"),
113            Options::IpV4Endpoint { ip, protocol, port } => {
114                writer.write_u8(u8::from(OptionType::IpV4Endpoint))?;
115                writer.write_u8(0)?;
116                writer.write_u32_be(ip.to_bits())?;
117                writer.write_u8(0)?;
118                writer.write_u8(u8::from(*protocol))?;
119                writer.write_u16_be(*port)?;
120                Ok(12)
121            }
122            Options::IpV6Endpoint => todo!("Options::Configuration not implemented"),
123            Options::IpV4Multicast => todo!("Options::Configuration not implemented"),
124            Options::IpV6Multicast => todo!("Options::Configuration not implemented"),
125            Options::IpV4SD => todo!("Options::Configuration not implemented"),
126            Options::IpV6SD => todo!("Options::Configuration not implemented"),
127        }
128    }
129
130    pub fn read<T: embedded_io::Read>(message_bytes: &mut T) -> Result<Self, Error> {
131        let length = message_bytes.read_u16_be()?;
132        let option_type = OptionType::try_from(message_bytes.read_u8()?)?;
133        let discard_flag = message_bytes.read_u8()? & 0x80 != 0;
134
135        match option_type {
136            OptionType::Configuration => {
137                todo!("Configuration option not implemented");
138            }
139            OptionType::LoadBalancing => {
140                todo!("LoadBalancing option not implemented");
141            }
142            OptionType::IpV4Endpoint => {
143                assert!(length == 9, "Invalid length for IpV4Endpoint");
144                assert!(!discard_flag, "Discard flag not set");
145                let ip = Ipv4Addr::from_bits(message_bytes.read_u32_be()?);
146                let reserved = message_bytes.read_u8()?;
147                assert!(reserved == 0, "Reserved byte not zero");
148                let protocol = TransportProtocol::try_from(message_bytes.read_u8()?)?;
149                let port = message_bytes.read_u16_be()?;
150                Ok(Options::IpV4Endpoint { ip, protocol, port })
151            }
152            OptionType::IpV6Endpoint => {
153                todo!("IpV6Endpoint option not implemented");
154            }
155            OptionType::IpV4Multicast => {
156                todo!("Multicast Option not implemented");
157            }
158            OptionType::IpV6Multicast => {
159                todo!("Multicast Option not implemented");
160            }
161            OptionType::IpV4SD => {
162                todo!("IpV4SD Option not implemented");
163            }
164            OptionType::IpV6SD => {
165                todo!("IpV6SD Option not implemented");
166            }
167        }
168    }
169}