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