1#![deny(missing_debug_implementations)]
10#![deny(missing_docs)]
11
12#![no_std]
61
62use core::{
63 net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
64 str::FromStr,
65};
66
67use crate::message::StunParseError;
68
69pub mod attribute;
70pub mod data;
71pub mod message;
72
73extern crate alloc;
74
75#[cfg(any(feature = "std", test))]
76extern crate std;
77
78#[derive(Debug, Clone, Copy, PartialEq, Eq)]
80#[repr(u32)]
81pub enum TransportType {
82 Udp,
84 Tcp,
86}
87
88#[derive(Debug, thiserror::Error)]
90pub enum ParseTransportTypeError {
91 #[error("Unknown transport value was provided")]
93 UnknownTransport,
94}
95
96impl FromStr for TransportType {
97 type Err = ParseTransportTypeError;
98
99 fn from_str(s: &str) -> Result<Self, Self::Err> {
100 match s {
101 "UDP" => Ok(TransportType::Udp),
102 "TCP" => Ok(TransportType::Tcp),
103 _ => Err(ParseTransportTypeError::UnknownTransport),
104 }
105 }
106}
107
108impl core::fmt::Display for TransportType {
109 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
110 match &self {
111 TransportType::Udp => f.pad("UDP"),
112 TransportType::Tcp => f.pad("TCP"),
113 }
114 }
115}
116
117#[derive(Debug, Clone, Copy, PartialEq, Eq)]
119pub enum AddressFamily {
120 IPV4,
122 IPV6,
124}
125
126impl AddressFamily {
127 pub(crate) fn to_byte(self) -> u8 {
128 match self {
129 AddressFamily::IPV4 => 0x1,
130 AddressFamily::IPV6 => 0x2,
131 }
132 }
133
134 pub(crate) fn from_byte(byte: u8) -> Result<AddressFamily, StunParseError> {
135 match byte {
136 0x1 => Ok(AddressFamily::IPV4),
137 0x2 => Ok(AddressFamily::IPV6),
138 _ => Err(StunParseError::InvalidAttributeData),
139 }
140 }
141}
142
143impl From<&SocketAddr> for AddressFamily {
144 fn from(value: &SocketAddr) -> Self {
145 match value {
146 SocketAddr::V4(_) => Self::IPV4,
147 SocketAddr::V6(_) => Self::IPV6,
148 }
149 }
150}
151
152impl From<&SocketAddrV4> for AddressFamily {
153 fn from(_value: &SocketAddrV4) -> Self {
154 Self::IPV4
155 }
156}
157
158impl From<&SocketAddrV6> for AddressFamily {
159 fn from(_value: &SocketAddrV6) -> Self {
160 Self::IPV6
161 }
162}
163
164impl From<&IpAddr> for AddressFamily {
165 fn from(value: &IpAddr) -> Self {
166 match value {
167 IpAddr::V4(_) => Self::IPV4,
168 IpAddr::V6(_) => Self::IPV6,
169 }
170 }
171}
172
173impl From<&Ipv4Addr> for AddressFamily {
174 fn from(_value: &Ipv4Addr) -> Self {
175 Self::IPV4
176 }
177}
178
179impl From<&Ipv6Addr> for AddressFamily {
180 fn from(_value: &Ipv6Addr) -> Self {
181 Self::IPV6
182 }
183}
184
185impl core::fmt::Display for AddressFamily {
186 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
187 match self {
188 AddressFamily::IPV4 => write!(f, "IPV4"),
189 AddressFamily::IPV6 => write!(f, "IPV6"),
190 }
191 }
192}
193
194pub mod prelude {
196 pub use crate::attribute::{
197 Attribute, AttributeExt, AttributeFromRaw, AttributeStaticType, AttributeWrite,
198 AttributeWriteExt,
199 };
200 pub use crate::message::{MessageWrite, MessageWriteExt};
201}
202
203#[cfg(test)]
204pub(crate) mod tests {
205 use alloc::borrow::ToOwned;
206 use alloc::format;
207 use alloc::string::{String, ToString};
208 use tracing::subscriber::DefaultGuard;
209 use tracing_subscriber::layer::SubscriberExt;
210 use tracing_subscriber::Layer;
211
212 use super::*;
213
214 pub fn test_init_log() -> DefaultGuard {
215 let level_filter = std::env::var("STUN_LOG")
216 .or(std::env::var("RUST_LOG"))
217 .ok()
218 .and_then(|var| var.parse::<tracing_subscriber::filter::Targets>().ok())
219 .unwrap_or(
220 tracing_subscriber::filter::Targets::new().with_default(tracing::Level::TRACE),
221 );
222 let registry = tracing_subscriber::registry().with(
223 tracing_subscriber::fmt::layer()
224 .with_file(true)
225 .with_line_number(true)
226 .with_level(true)
227 .with_target(false)
228 .with_test_writer()
229 .with_filter(level_filter),
230 );
231 tracing::subscriber::set_default(registry)
232 }
233
234 #[test]
235 fn parse_transport_type() {
236 assert!(matches!("UDP".parse(), Ok(TransportType::Udp)));
237 assert!(matches!("TCP".parse(), Ok(TransportType::Tcp)));
238 assert!(matches!(
239 TransportType::from_str("Random"),
240 Err(ParseTransportTypeError::UnknownTransport)
241 ));
242 }
243
244 #[test]
245 fn transport_type_str() {
246 assert_eq!(TransportType::Udp.to_string(), String::from("UDP"));
247 assert_eq!(TransportType::Tcp.to_string(), String::from("TCP"));
248 }
249
250 #[test]
251 fn address_family() {
252 assert_eq!(AddressFamily::IPV4.to_byte(), 1);
253 assert_eq!(AddressFamily::from_byte(1).unwrap(), AddressFamily::IPV4);
254 assert_eq!(format!("{}", AddressFamily::IPV4), "IPV4".to_owned());
255 assert_eq!(AddressFamily::IPV6.to_byte(), 2);
256 assert_eq!(AddressFamily::from_byte(2).unwrap(), AddressFamily::IPV6);
257 assert_eq!(format!("{}", AddressFamily::IPV6), "IPV6".to_owned());
258 assert!(matches!(
259 AddressFamily::from_byte(3),
260 Err(StunParseError::InvalidAttributeData)
261 ));
262 let ipv4_addr: SocketAddr = "127.0.0.1:1".parse().unwrap();
263 assert_eq!(AddressFamily::from(&ipv4_addr), AddressFamily::IPV4);
264 assert_eq!(AddressFamily::from(&ipv4_addr.ip()), AddressFamily::IPV4);
265 let SocketAddr::V4(ipv4_addr) = ipv4_addr else {
266 unreachable!();
267 };
268 assert_eq!(AddressFamily::from(&ipv4_addr), AddressFamily::IPV4);
269 assert_eq!(AddressFamily::from(ipv4_addr.ip()), AddressFamily::IPV4);
270 let ipv6_addr: SocketAddr = "[::1]:1".parse().unwrap();
271 assert_eq!(AddressFamily::from(&ipv6_addr), AddressFamily::IPV6);
272 assert_eq!(AddressFamily::from(&ipv6_addr.ip()), AddressFamily::IPV6);
273 let SocketAddr::V6(ipv6_addr) = ipv6_addr else {
274 unreachable!();
275 };
276 assert_eq!(AddressFamily::from(&ipv6_addr), AddressFamily::IPV6);
277 assert_eq!(AddressFamily::from(ipv6_addr.ip()), AddressFamily::IPV6);
278 }
279}