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