stun_types/
lib.rs

1// Copyright (C) 2020 Matthew Waters <matthew@centricular.com>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9#![deny(missing_debug_implementations)]
10#![deny(missing_docs)]
11
12//! # stun-types
13//!
14//! An implementation of parsing and writing STUN messages and attributes. This implementation is
15//! trait based and supports definitions of [`Attribute`](attribute::Attribute)s that are external
16//! to this crate.
17//!
18//! This is based on the following standards:
19//! - [RFC8489]
20//! - [RFC5389]
21//! - [RFC3489]
22//!
23//! [RFC8489]: https://tools.ietf.org/html/rfc8489
24//! [RFC5389]: https://tools.ietf.org/html/rfc5389
25//! [RFC3489]: https://tools.ietf.org/html/rfc3489
26//!
27//! ## Examples
28//!
29//! See the [`message`] and [`attribute`] module documentation for examples on use.
30
31use std::str::FromStr;
32
33pub mod attribute;
34pub mod data;
35pub mod message;
36
37/// The transport family
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39#[repr(u32)]
40pub enum TransportType {
41    /// The UDP transport
42    Udp,
43    /// The TCP transport
44    Tcp,
45}
46
47/// Errors when parsing a [`TransportType`]
48#[derive(Debug, thiserror::Error)]
49pub enum ParseTransportTypeError {
50    /// An unknown transport value was provided
51    #[error("Unknown transport value was provided")]
52    UnknownTransport,
53}
54
55impl FromStr for TransportType {
56    type Err = ParseTransportTypeError;
57
58    fn from_str(s: &str) -> Result<Self, Self::Err> {
59        match s {
60            "UDP" => Ok(TransportType::Udp),
61            "TCP" => Ok(TransportType::Tcp),
62            _ => Err(ParseTransportTypeError::UnknownTransport),
63        }
64    }
65}
66
67impl std::fmt::Display for TransportType {
68    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69        match &self {
70            TransportType::Udp => f.pad("UDP"),
71            TransportType::Tcp => f.pad("TCP"),
72        }
73    }
74}
75
76/// Prelude module for traits
77pub mod prelude {
78    pub use crate::attribute::{
79        Attribute, AttributeExt, AttributeFromRaw, AttributeStaticType, AttributeWrite,
80        AttributeWriteExt,
81    };
82}
83
84#[cfg(test)]
85pub(crate) mod tests {
86    use tracing::subscriber::DefaultGuard;
87    use tracing_subscriber::layer::SubscriberExt;
88    use tracing_subscriber::Layer;
89
90    use super::*;
91
92    pub fn test_init_log() -> DefaultGuard {
93        let level_filter = std::env::var("STUN_LOG")
94            .or(std::env::var("RUST_LOG"))
95            .ok()
96            .and_then(|var| var.parse::<tracing_subscriber::filter::Targets>().ok())
97            .unwrap_or(
98                tracing_subscriber::filter::Targets::new().with_default(tracing::Level::TRACE),
99            );
100        let registry = tracing_subscriber::registry().with(
101            tracing_subscriber::fmt::layer()
102                .with_file(true)
103                .with_line_number(true)
104                .with_level(true)
105                .with_target(false)
106                .with_test_writer()
107                .with_filter(level_filter),
108        );
109        tracing::subscriber::set_default(registry)
110    }
111
112    #[test]
113    fn parse_transport_type() {
114        assert!(matches!("UDP".parse(), Ok(TransportType::Udp)));
115        assert!(matches!("TCP".parse(), Ok(TransportType::Tcp)));
116        assert!(matches!(
117            TransportType::from_str("Random"),
118            Err(ParseTransportTypeError::UnknownTransport)
119        ));
120    }
121
122    #[test]
123    fn transport_type_str() {
124        assert_eq!(TransportType::Udp.to_string(), String::from("UDP"));
125        assert_eq!(TransportType::Tcp.to_string(), String::from("TCP"));
126    }
127}