1#[cfg(feature = "api")]
2pub mod api;
3
4#[cfg(feature = "prometheus")]
5pub mod prometheus;
6
7pub mod codec;
8pub mod config;
9pub mod handler;
10pub mod server;
11pub mod service;
12pub mod statistics;
13
14pub mod prelude {
15 pub use super::codec::{
16 channel_data::*,
17 crypto::*,
18 message::{
19 attributes::{error::*, *},
20 methods::*,
21 *,
22 },
23 *,
24 };
25
26 pub use super::service::{
27 session::{ports::*, *},
28 *,
29 };
30}
31
32use self::{config::Config, handler::Handler, service::ServiceOptions, statistics::Statistics};
33
34use tokio::task::JoinSet;
35
36#[rustfmt::skip]
37pub(crate) static SOFTWARE: &str = concat!(
38 "turn-rs.",
39 env!("CARGO_PKG_VERSION")
40);
41
42pub(crate) type Service = service::Service<Handler>;
43
44pub async fn start_server(config: Config) -> anyhow::Result<()> {
48 let statistics = Statistics::default();
49 let service = service::Service::new(ServiceOptions {
50 realm: config.server.realm.clone(),
51 port_range: config.server.port_range,
52 interfaces: config.server.get_external_addresses(),
53 handler: Handler::new(config.clone(), statistics.clone()).await?,
54 });
55
56 {
57 let mut workers = JoinSet::new();
58
59 workers.spawn(server::start_server(
60 config.clone(),
61 service.clone(),
62 statistics.clone(),
63 ));
64
65 #[cfg(feature = "prometheus")]
66 workers.spawn(prometheus::start_server(config.clone()));
67
68 #[cfg(feature = "api")]
69 workers.spawn(api::start_server(config, service, statistics));
70
71 if let Some(res) = workers.join_next().await {
72 workers.abort_all();
73
74 return res?;
75 }
76 }
77
78 Ok(())
79}