medea_turn/
lib.rs

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
168// TODO: Try remove once `bytecodec` is updated to new major version.
169/// Not really used, for surviving `minimal-versions` check only.
170mod minimal_versions {
171    use byteorder1 as _;
172    use trackable1 as _;
173}
174
175/// Authentication handler.
176pub trait AuthHandler {
177    /// Performs authentication of the specified user, returning its ICE
178    /// password on success.
179    ///
180    /// # Errors
181    ///
182    /// If authentication fails.
183    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/// [`AuthHandler`] always returning an [`Error`].
203///
204/// Can be used in type signatures when [TURN] is disabled.
205///
206/// [TURN]: https://en.wikipedia.org/wiki/TURN
207#[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/// Possible errors of a [STUN]/[TURN] [`Server`].
222///
223/// [STUN]: https://en.wikipedia.org/wiki/STUN
224/// [TURN]: https://en.wikipedia.org/wiki/TURN
225#[derive(Debug, Display, Eq, From, PartialEq, StdError)]
226#[non_exhaustive]
227pub enum Error {
228    /// Failed to allocate new relay connection, since maximum retires count
229    /// exceeded.
230    #[display("turn: max retries exceeded")]
231    MaxRetriesExceeded,
232
233    /// {eer address is part of a different address family than that of the
234    /// relayed transport address of the allocation.
235    #[display("error code 443: peer address family mismatch")]
236    PeerAddressFamilyMismatch,
237
238    /// Error when trying to perform action after closing server.
239    #[display("use of closed network connection")]
240    Closed,
241
242    /// Channel binding request failed, since channel number is currently bound
243    /// to a different transport address.
244    #[display("cannot use the same channel number with different peer")]
245    SameChannelDifferentPeer,
246
247    /// Channel binding request failed, since the transport address is currently
248    /// bound to a different channel number.
249    #[display("cannot use the same peer number with different channel")]
250    SamePeerDifferentChannel,
251
252    /// Cannot create allocation with zero lifetime.
253    #[display("allocations must not be created with a lifetime of 0")]
254    LifetimeZero,
255
256    /// Cannot create allocation for the same five-tuple.
257    #[display("allocation attempt created with duplicate 5-TUPLE")]
258    DupeFiveTuple,
259
260    /// Authentication error.
261    #[display("no such user exists")]
262    NoSuchUser,
263
264    /// Unsupported request class.
265    #[display("unexpected class")]
266    UnexpectedClass,
267
268    /// Allocation request failed, since allocation already exists for the
269    /// provided [`FiveTuple`].
270    #[display("relay already allocated for 5-TUPLE")]
271    RelayAlreadyAllocatedForFiveTuple,
272
273    /// [STUN] message doesn't have a required attribute.
274    ///
275    /// [STUN]: https://en.wikipedia.org/wiki/STUN
276    #[display("requested attribute not found")]
277    AttributeNotFound,
278
279    /// [STUN] message contains wrong [`MessageIntegrity`].
280    ///
281    /// [`MessageIntegrity`]: attr::MessageIntegrity
282    /// [STUN]: https://en.wikipedia.org/wiki/STUN
283    #[display("message integrity mismatch")]
284    IntegrityMismatch,
285
286    /// [DONT-FRAGMENT][1] attribute is not supported.
287    ///
288    /// [1]: https://tools.ietf.org/html/rfc5766#section-14.8
289    #[display("no support for DONT-FRAGMENT")]
290    NoDontFragmentSupport,
291
292    /// Allocation request cannot have both [RESERVATION-TOKEN][1] and
293    /// [EVEN-PORT][2].
294    ///
295    /// [1]: https://tools.ietf.org/html/rfc5766#section-14.9
296    /// [2]: https://tools.ietf.org/html/rfc5766#section-14.6
297    #[display("Request must not contain RESERVATION-TOKEN and EVEN-PORT")]
298    RequestWithReservationTokenAndEvenPort,
299
300    /// Allocation request cannot contain both [RESERVATION-TOKEN][1] and
301    /// [REQUESTED-ADDRESS-FAMILY][2].
302    ///
303    /// [1]: https://tools.ietf.org/html/rfc5766#section-14.9
304    /// [2]: https://tools.ietf.org/html/rfc6156#section-4.1.1
305    #[display(
306        "Request must not contain RESERVATION-TOKEN \
307            and REQUESTED-ADDRESS-FAMILY"
308    )]
309    RequestWithReservationTokenAndReqAddressFamily,
310
311    /// No allocation for the provided [`FiveTuple`].
312    #[display("no allocation found")]
313    NoAllocationFound,
314
315    /// The specified protocol is not supported.
316    #[display("allocation requested unsupported proto")]
317    UnsupportedRelayProto,
318
319    /// Failed to handle [Send Indication][1], since there is no permission for
320    /// the provided address.
321    ///
322    /// [1]: https://tools.ietf.org/html/rfc5766#section-10.2
323    #[display("unable to handle send-indication, no permission added")]
324    NoPermission,
325
326    /// Failed to handle channel data, since there is no binding for the
327    /// provided channel.
328    #[display("no such channel bind")]
329    NoSuchChannelBind,
330
331    /// Failed to encode message.
332    #[display("Failed to encode STUN/TURN message: {_0:?}")]
333    #[from(ignore)]
334    Encode(#[error(not(source))] bytecodec::ErrorKind),
335
336    /// Failed to send message.
337    #[display("Transport error: {_0}")]
338    Transport(transport::Error),
339}