Skip to main content

turn_types/
lib.rs

1// Copyright (C) 2025 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// SPDX-License-Identifier: MIT OR Apache-2.0
10
11#![deny(missing_debug_implementations)]
12#![deny(missing_docs)]
13#![cfg_attr(docsrs, feature(doc_cfg))]
14
15//! # turn-types
16//!
17//! `turn-types` provides an implementation for two main things related to TURN clients and servers:
18//! 1. TURN specific STUN attributes using the [stun-types] crate.
19//! 2. Parsing to and from the actual data sent and received on the wire between a TURN client and
20//!    a TURN server.
21//!
22//! This crate implements the STUN attributes and methods presented in the following standards:
23//! - [RFC5766]: Traversal Using Relays around NAT (TURN).
24//! - [RFC6062]: Traversal Using Relays around NAT (TURN) Extensions for TCP Allocations
25//! - [RFC6156]: Traversal Using Relays around NAT (TURN) Extension for IPv6
26//! - [RFC8656]: Traversal Using Relays around NAT (TURN): Relay Extensions to Session
27//!   Traversal Utilities for NAT (STUN)
28//!
29//! [stun-types]: https://docs.rs/stun-types/latest/stun_types
30//! [RFC5766]: https://tools.ietf.org/html/rfc5766
31//! [RFC6062]: https://tools.ietf.org/html/rfc6062
32//! [RFC6156]: https://tools.ietf.org/html/rfc6156
33//! [RFC8656]: https://tools.ietf.org/html/rfc8656
34
35#![no_std]
36
37extern crate alloc;
38
39#[cfg(any(feature = "std", test))]
40extern crate std;
41
42pub use stun_types as stun;
43pub mod attribute;
44pub mod channel;
45pub mod message;
46pub mod tcp;
47pub mod transmit;
48
49pub use stun_proto::Instant;
50
51/// Public prelude.
52pub mod prelude {
53    pub use crate::transmit::DelayedTransmitBuild;
54}
55
56use alloc::borrow::ToOwned;
57use alloc::string::{String, ToString};
58use stun_types::message::{LongTermCredentials, LongTermKeyCredentials};
59pub use stun_types::{AddressFamily, TransportType};
60
61/// Initialize some debugging functionality of the library.
62///
63/// It is not required to call this function, however doing so allows debug functionality of
64/// stun-types to print much more human readable descriptions of attributes and messages.
65pub fn debug_init() {
66    attribute::attributes_init();
67    message::debug_init();
68}
69
70/// Credentials used for a TURN user.
71#[derive(Debug, Clone, PartialEq, Eq)]
72pub struct TurnCredentials {
73    username: String,
74    password: String,
75}
76
77impl From<TurnCredentials> for LongTermCredentials {
78    fn from(value: TurnCredentials) -> Self {
79        LongTermCredentials::new(value.username, value.password)
80    }
81}
82
83impl TurnCredentials {
84    /// Transform these credentials into some `LongTermCredentials` for use in a STUN context.
85    pub fn into_long_term_credentials(self, realm: &str) -> LongTermKeyCredentials {
86        LongTermKeyCredentials::new(self.username, self.password, realm.to_string())
87    }
88
89    /// Construct a new set of [`TurnCredentials`]
90    pub fn new(username: &str, password: &str) -> Self {
91        Self {
92            username: username.to_owned(),
93            password: password.to_owned(),
94        }
95    }
96
97    /// The username of the credentials.
98    pub fn username(&self) -> &str {
99        &self.username
100    }
101
102    /// The password of the credentials.
103    pub fn password(&self) -> &str {
104        &self.password
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    use tracing::subscriber::DefaultGuard;
111    use tracing_subscriber::layer::SubscriberExt;
112    use tracing_subscriber::Layer;
113
114    pub fn test_init_log() -> DefaultGuard {
115        crate::debug_init();
116        let level_filter = std::env::var("TURN_LOG")
117            .or(std::env::var("RUST_LOG"))
118            .ok()
119            .and_then(|var| var.parse::<tracing_subscriber::filter::Targets>().ok())
120            .unwrap_or(
121                tracing_subscriber::filter::Targets::new().with_default(tracing::Level::TRACE),
122            );
123        let registry = tracing_subscriber::registry().with(
124            tracing_subscriber::fmt::layer()
125                .with_file(true)
126                .with_line_number(true)
127                .with_level(true)
128                .with_target(false)
129                .with_test_writer()
130                .with_filter(level_filter),
131        );
132        tracing::subscriber::set_default(registry)
133    }
134}