use std::net::SocketAddr;
use tokio::net::UdpSocket;
use tokio::time::Duration;
use turn::relay::relay_range::RelayAddressGeneratorRanges;
use turn::server::config::ConnConfig;
use turn::server::config::ServerConfig;
use turn::server::Server as TurnServer;
use std::sync::Arc;
use turn::auth;
use turn::auth::AuthHandler;
use turn::auth::LongTermAuthHandler;
use turn::Error;
use anyhow::Result as AnyhowResult;
use regex::Regex;
use std::collections::HashMap;
use std::net::IpAddr;
use std::result::Result;
use std::str::FromStr;
use webrtc_util::vnet::net::*;
use serde::Deserialize;
pub const TURN_MIN_PORT: u16 = 32768;
pub const TURN_MAX_PORT: u16 = 46883;
pub const SFU_MIN_PORT: u16 = 46884;
pub const SFU_MAX_PORT: u16 = 60999;
#[derive(Clone, Default, Deserialize)]
pub(super) struct TurnAuth {
#[serde(rename = "credentials")]
#[allow(dead_code)]
credentials: String,
secret: Option<String>,
}
#[derive(Clone, Default, Deserialize)]
pub(super) struct TurnConfig {
#[serde(rename = "enabled")]
pub(super) enabled: bool,
#[serde(rename = "realm")]
realm: String,
#[serde(rename = "address")]
address: String,
#[allow(dead_code)]
cert: Option<String>,
#[allow(dead_code)]
key: Option<String>,
auth: TurnAuth,
pub(super) port_range: Option<Vec<u16>>,
}
struct CustomAuthHandler {
users_map: HashMap<String, Vec<u8>>,
}
impl CustomAuthHandler {
fn new(user_map: HashMap<String, Vec<u8>>) -> Self {
Self {
users_map: user_map,
}
}
}
impl AuthHandler for CustomAuthHandler {
fn auth_handle(
&self,
username: &str,
realm: &str,
_src_addr: SocketAddr,
) -> Result<Vec<u8>, Error> {
if let Some(val) = self.users_map.get(&username.to_string()) {
return Ok(val.clone());
}
log::trace!("realm val: {}", realm);
Err(Error::ErrNilConn)
}
}
pub(super) async fn init_turn_server(
conf: TurnConfig,
auth: Option<Arc<dyn AuthHandler + Send + Sync>>,
) -> AnyhowResult<TurnServer> {
let conn = Arc::new(UdpSocket::bind(conf.address.clone()).await?);
println!("listening {}...", conn.local_addr()?);
let mut new_auth: Option<Arc<dyn AuthHandler + Send + Sync>> = auth;
if new_auth.is_none() {
if let Some(secret) = conf.auth.secret {
new_auth = Some(Arc::new(LongTermAuthHandler::new(secret)));
} else {
let mut users_map: HashMap<String, Vec<u8>> = HashMap::new();
let re = Regex::new(r"(\w+)=(\w+)").unwrap();
for caps in re.captures_iter(conf.realm.clone().as_str()) {
let username = caps.get(1).unwrap().as_str();
let username_string = username.to_string();
let password = caps.get(2).unwrap().as_str();
users_map.insert(
username_string,
auth::generate_auth_key(username, conf.realm.clone().as_str(), password),
);
}
if users_map.is_empty() {
log::error!("no turn auth provided.");
}
new_auth = Some(Arc::new(CustomAuthHandler::new(users_map)))
}
}
let mut min_port: u16 = TURN_MIN_PORT;
let mut max_port: u16 = TURN_MAX_PORT;
if let Some(port_range) = conf.port_range {
if port_range.len() == 2 {
min_port = port_range[0];
max_port = port_range[1];
}
}
let addr: Vec<&str> = conf.address.split(':').collect();
let conn_configs = vec![ConnConfig {
conn,
relay_addr_generator: Box::new(RelayAddressGeneratorRanges {
min_port,
max_port,
max_retries: 1,
relay_address: IpAddr::from_str(addr[0])?,
address: "0.0.0.0".to_owned(),
net: Arc::new(Net::new(Some(NetConfig::default()))),
}),
}];
let turn_server = TurnServer::new(ServerConfig {
conn_configs,
realm: conf.realm,
auth_handler: new_auth.unwrap(),
channel_bind_timeout: Duration::from_secs(5),
})
.await?;
Ok(turn_server)
}