1#![cfg_attr(any(doc, test), doc = include_str!("../README.md"))]
2#![cfg_attr(not(any(doc, test)), doc = env!("CARGO_PKG_NAME"))]
3#![deny(nonstandard_style, rustdoc::all, trivial_casts, trivial_numeric_casts)]
4#![forbid(non_ascii_idents, unsafe_code)]
5#![warn(
6 clippy::absolute_paths,
7 clippy::allow_attributes,
8 clippy::allow_attributes_without_reason,
9 clippy::as_conversions,
10 clippy::as_pointer_underscore,
11 clippy::as_ptr_cast_mut,
12 clippy::assertions_on_result_states,
13 clippy::branches_sharing_code,
14 clippy::cfg_not_test,
15 clippy::clear_with_drain,
16 clippy::clone_on_ref_ptr,
17 clippy::collection_is_never_read,
18 clippy::create_dir,
19 clippy::dbg_macro,
20 clippy::debug_assert_with_mut_call,
21 clippy::decimal_literal_representation,
22 clippy::default_union_representation,
23 clippy::derive_partial_eq_without_eq,
24 clippy::doc_include_without_cfg,
25 clippy::empty_drop,
26 clippy::empty_structs_with_brackets,
27 clippy::equatable_if_let,
28 clippy::empty_enum_variants_with_brackets,
29 clippy::exit,
30 clippy::expect_used,
31 clippy::fallible_impl_from,
32 clippy::filetype_is_file,
33 clippy::float_cmp_const,
34 clippy::fn_to_numeric_cast_any,
35 clippy::get_unwrap,
36 clippy::if_then_some_else_none,
37 clippy::imprecise_flops,
38 clippy::infinite_loop,
39 clippy::iter_on_empty_collections,
40 clippy::iter_on_single_items,
41 clippy::iter_over_hash_type,
42 clippy::iter_with_drain,
43 clippy::large_include_file,
44 clippy::large_stack_frames,
45 clippy::let_underscore_untyped,
46 clippy::literal_string_with_formatting_args,
47 clippy::lossy_float_literal,
48 clippy::map_err_ignore,
49 clippy::map_with_unused_argument_over_ranges,
50 clippy::mem_forget,
51 clippy::missing_assert_message,
52 clippy::missing_asserts_for_indexing,
53 clippy::missing_const_for_fn,
54 clippy::missing_docs_in_private_items,
55 clippy::module_name_repetitions,
56 clippy::multiple_inherent_impl,
57 clippy::multiple_unsafe_ops_per_block,
58 clippy::mutex_atomic,
59 clippy::mutex_integer,
60 clippy::needless_collect,
61 clippy::needless_pass_by_ref_mut,
62 clippy::needless_raw_strings,
63 clippy::non_zero_suggestions,
64 clippy::nonstandard_macro_braces,
65 clippy::option_if_let_else,
66 clippy::or_fun_call,
67 clippy::panic_in_result_fn,
68 clippy::partial_pub_fields,
69 clippy::pathbuf_init_then_push,
70 clippy::pedantic,
71 clippy::precedence_bits,
72 clippy::print_stderr,
73 clippy::print_stdout,
74 clippy::pub_without_shorthand,
75 clippy::rc_buffer,
76 clippy::rc_mutex,
77 clippy::read_zero_byte_vec,
78 clippy::redundant_clone,
79 clippy::redundant_test_prefix,
80 clippy::redundant_type_annotations,
81 clippy::renamed_function_params,
82 clippy::ref_patterns,
83 clippy::rest_pat_in_fully_bound_structs,
84 clippy::return_and_then,
85 clippy::same_name_method,
86 clippy::semicolon_inside_block,
87 clippy::set_contains_or_insert,
88 clippy::shadow_unrelated,
89 clippy::significant_drop_in_scrutinee,
90 clippy::significant_drop_tightening,
91 clippy::single_option_map,
92 clippy::str_to_string,
93 clippy::string_add,
94 clippy::string_lit_as_bytes,
95 clippy::string_lit_chars_any,
96 clippy::string_slice,
97 clippy::string_to_string,
98 clippy::suboptimal_flops,
99 clippy::suspicious_operation_groupings,
100 clippy::suspicious_xor_used_as_pow,
101 clippy::tests_outside_test_module,
102 clippy::todo,
103 clippy::too_long_first_doc_paragraph,
104 clippy::trailing_empty_array,
105 clippy::transmute_undefined_repr,
106 clippy::trivial_regex,
107 clippy::try_err,
108 clippy::undocumented_unsafe_blocks,
109 clippy::unimplemented,
110 clippy::uninhabited_references,
111 clippy::unnecessary_safety_comment,
112 clippy::unnecessary_safety_doc,
113 clippy::unnecessary_self_imports,
114 clippy::unnecessary_struct_initialization,
115 clippy::unused_peekable,
116 clippy::unused_result_ok,
117 clippy::unused_trait_names,
118 clippy::unwrap_in_result,
119 clippy::unwrap_used,
120 clippy::use_debug,
121 clippy::use_self,
122 clippy::useless_let_if_seq,
123 clippy::verbose_file_reads,
124 clippy::while_float,
125 clippy::wildcard_enum_match_arm,
126 ambiguous_negative_literals,
127 closure_returning_async_block,
128 future_incompatible,
129 impl_trait_redundant_captures,
130 let_underscore_drop,
131 macro_use_extern_crate,
132 meta_variable_misuse,
133 missing_copy_implementations,
134 missing_debug_implementations,
135 missing_docs,
136 redundant_lifetimes,
137 rust_2018_idioms,
138 single_use_lifetimes,
139 unit_bindings,
140 unnameable_types,
141 unreachable_pub,
142 unstable_features,
143 unused,
144 variant_size_differences
145)]
146
147mod allocation;
148pub mod attr;
149pub mod chandata;
150pub mod relay;
151mod server;
152pub mod transport;
153
154use std::{net::SocketAddr, sync::Arc};
155
156use derive_more::with_trait::{Display, Error as StdError, From};
157use secrecy::SecretString;
158
159#[cfg(test)]
160pub(crate) use self::allocation::Allocation;
161pub(crate) use self::transport::Transport;
162pub use self::{
163 allocation::{FiveTuple, Info as AllocationInfo},
164 chandata::ChannelData,
165 server::{Config as ServerConfig, Server, TurnConfig},
166};
167
168mod minimal_versions {
171 use byteorder1 as _;
172 use trackable1 as _;
173}
174
175pub trait AuthHandler {
177 fn auth_handle(
184 &self,
185 username: &str,
186 realm: &str,
187 src_addr: SocketAddr,
188 ) -> Result<SecretString, Error>;
189}
190
191impl<T: ?Sized + AuthHandler> AuthHandler for Arc<T> {
192 fn auth_handle(
193 &self,
194 username: &str,
195 realm: &str,
196 src_addr: SocketAddr,
197 ) -> Result<SecretString, Error> {
198 (**self).auth_handle(username, realm, src_addr)
199 }
200}
201
202#[derive(Clone, Copy, Debug)]
208pub struct NoneAuthHandler;
209
210impl AuthHandler for NoneAuthHandler {
211 fn auth_handle(
212 &self,
213 _: &str,
214 _: &str,
215 _: SocketAddr,
216 ) -> Result<SecretString, Error> {
217 Err(Error::NoSuchUser)
218 }
219}
220
221#[derive(Debug, Display, Eq, From, PartialEq, StdError)]
226#[non_exhaustive]
227pub enum Error {
228 #[display("turn: max retries exceeded")]
231 MaxRetriesExceeded,
232
233 #[display("error code 443: peer address family mismatch")]
236 PeerAddressFamilyMismatch,
237
238 #[display("use of closed network connection")]
240 Closed,
241
242 #[display("cannot use the same channel number with different peer")]
245 SameChannelDifferentPeer,
246
247 #[display("cannot use the same peer number with different channel")]
250 SamePeerDifferentChannel,
251
252 #[display("allocations must not be created with a lifetime of 0")]
254 LifetimeZero,
255
256 #[display("allocation attempt created with duplicate 5-TUPLE")]
258 DupeFiveTuple,
259
260 #[display("no such user exists")]
262 NoSuchUser,
263
264 #[display("unexpected class")]
266 UnexpectedClass,
267
268 #[display("relay already allocated for 5-TUPLE")]
271 RelayAlreadyAllocatedForFiveTuple,
272
273 #[display("requested attribute not found")]
277 AttributeNotFound,
278
279 #[display("message integrity mismatch")]
284 IntegrityMismatch,
285
286 #[display("no support for DONT-FRAGMENT")]
290 NoDontFragmentSupport,
291
292 #[display("Request must not contain RESERVATION-TOKEN and EVEN-PORT")]
298 RequestWithReservationTokenAndEvenPort,
299
300 #[display(
306 "Request must not contain RESERVATION-TOKEN \
307 and REQUESTED-ADDRESS-FAMILY"
308 )]
309 RequestWithReservationTokenAndReqAddressFamily,
310
311 #[display("no allocation found")]
313 NoAllocationFound,
314
315 #[display("allocation requested unsupported proto")]
317 UnsupportedRelayProto,
318
319 #[display("unable to handle send-indication, no permission added")]
324 NoPermission,
325
326 #[display("no such channel bind")]
329 NoSuchChannelBind,
330
331 #[display("Failed to encode STUN/TURN message: {_0:?}")]
333 #[from(ignore)]
334 Encode(#[error(not(source))] bytecodec::ErrorKind),
335
336 #[display("Transport error: {_0}")]
338 Transport(transport::Error),
339}