mirror of
https://gitlab.com/famedly/conduit.git
synced 2025-06-27 16:35:59 +00:00
feat(turn): move config to table & error when no config is set
This commit is contained in:
parent
a9ff97e527
commit
dbc1daaefb
4 changed files with 106 additions and 89 deletions
|
@ -7,17 +7,18 @@
|
||||||
## Edit/Add a few settings to your existing conduit.toml
|
## Edit/Add a few settings to your existing conduit.toml
|
||||||
|
|
||||||
```
|
```
|
||||||
|
[turn]
|
||||||
# Refer to your Coturn settings.
|
# Refer to your Coturn settings.
|
||||||
# `your.turn.url` has to match the REALM setting of your Coturn as well as `transport`.
|
# `your.turn.url` has to match the REALM setting of your Coturn as well as `transport`.
|
||||||
turn_uris = ["turn:your.turn.url?transport=udp", "turn:your.turn.url?transport=tcp"]
|
uris = ["turn:your.turn.url?transport=udp", "turn:your.turn.url?transport=tcp"]
|
||||||
|
|
||||||
# static-auth-secret of your turnserver
|
# static-auth-secret of your turnserver
|
||||||
turn_secret = "ADD SECRET HERE"
|
secret = "ADD SECRET HERE"
|
||||||
|
|
||||||
# If you have your TURN server configured to use a username and password
|
# If you have your TURN server configured to use a username and password
|
||||||
# you can provide these information too. In this case comment out `turn_secret above`!
|
# you can provide these information too. In this case comment out `turn_secret above`!
|
||||||
#turn_username = ""
|
#username = ""
|
||||||
#turn_password = ""
|
#password = ""
|
||||||
```
|
```
|
||||||
|
|
||||||
## Apply settings
|
## Apply settings
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
use crate::{services, Result, Ruma};
|
use crate::{config::TurnAuth, services, Error, Result, Ruma};
|
||||||
use base64::{engine::general_purpose, Engine as _};
|
use base64::{engine::general_purpose, Engine as _};
|
||||||
use hmac::{Hmac, Mac};
|
use hmac::{Hmac, Mac};
|
||||||
use ruma::{api::client::voip::get_turn_server_info, SecondsSinceUnixEpoch};
|
use ruma::{
|
||||||
|
api::client::{error::ErrorKind, voip::get_turn_server_info},
|
||||||
|
SecondsSinceUnixEpoch,
|
||||||
|
};
|
||||||
use sha1::Sha1;
|
use sha1::Sha1;
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
|
|
||||||
|
@ -9,40 +12,41 @@ type HmacSha1 = Hmac<Sha1>;
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/voip/turnServer`
|
/// # `GET /_matrix/client/r0/voip/turnServer`
|
||||||
///
|
///
|
||||||
/// TODO: Returns information about the recommended turn server.
|
/// Returns information about the recommended turn server.
|
||||||
pub async fn turn_server_route(
|
pub async fn turn_server_route(
|
||||||
body: Ruma<get_turn_server_info::v3::Request>,
|
body: Ruma<get_turn_server_info::v3::Request>,
|
||||||
) -> Result<get_turn_server_info::v3::Response> {
|
) -> Result<get_turn_server_info::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let turn_secret = services().globals.turn_secret().clone();
|
if let Some(turn) = services().globals.turn() {
|
||||||
|
let (username, password) = match turn.auth {
|
||||||
let (username, password) = if !turn_secret.is_empty() {
|
TurnAuth::Secret { secret } => {
|
||||||
let expiry = SecondsSinceUnixEpoch::from_system_time(
|
let expiry = SecondsSinceUnixEpoch::from_system_time(
|
||||||
SystemTime::now() + Duration::from_secs(services().globals.turn_ttl()),
|
SystemTime::now() + Duration::from_secs(turn.ttl),
|
||||||
)
|
)
|
||||||
.expect("time is valid");
|
.expect("time is valid");
|
||||||
|
|
||||||
let username: String = format!("{}:{}", expiry.get(), sender_user);
|
let username: String = format!("{}:{}", expiry.get(), sender_user);
|
||||||
|
|
||||||
let mut mac = HmacSha1::new_from_slice(turn_secret.as_bytes())
|
let mut mac = HmacSha1::new_from_slice(secret.as_bytes())
|
||||||
.expect("HMAC can take key of any size");
|
.expect("HMAC can take key of any size");
|
||||||
mac.update(username.as_bytes());
|
mac.update(username.as_bytes());
|
||||||
|
|
||||||
let password: String = general_purpose::STANDARD.encode(mac.finalize().into_bytes());
|
let password: String =
|
||||||
|
general_purpose::STANDARD.encode(mac.finalize().into_bytes());
|
||||||
|
|
||||||
(username, password)
|
(username, password)
|
||||||
} else {
|
}
|
||||||
(
|
TurnAuth::UserPass { username, password } => (username, password),
|
||||||
services().globals.turn_username().clone(),
|
|
||||||
services().globals.turn_password().clone(),
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(get_turn_server_info::v3::Response {
|
Ok(get_turn_server_info::v3::Response {
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
uris: services().globals.turn_uris().to_vec(),
|
uris: turn.uris,
|
||||||
ttl: Duration::from_secs(services().globals.turn_ttl()),
|
ttl: Duration::from_secs(turn.ttl),
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
Err(Error::BadRequest(ErrorKind::NotFound, "No TURN config set"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,17 +72,15 @@ pub struct Config {
|
||||||
pub trusted_servers: Vec<OwnedServerName>,
|
pub trusted_servers: Vec<OwnedServerName>,
|
||||||
#[serde(default = "default_log")]
|
#[serde(default = "default_log")]
|
||||||
pub log: String,
|
pub log: String,
|
||||||
#[serde(default)]
|
pub turn_username: Option<String>,
|
||||||
pub turn_username: String,
|
pub turn_password: Option<String>,
|
||||||
#[serde(default)]
|
pub turn_uris: Option<Vec<String>>,
|
||||||
pub turn_password: String,
|
pub turn_secret: Option<String>,
|
||||||
#[serde(default = "Vec::new")]
|
|
||||||
pub turn_uris: Vec<String>,
|
|
||||||
#[serde(default)]
|
|
||||||
pub turn_secret: String,
|
|
||||||
#[serde(default = "default_turn_ttl")]
|
#[serde(default = "default_turn_ttl")]
|
||||||
pub turn_ttl: u64,
|
pub turn_ttl: u64,
|
||||||
|
|
||||||
|
pub turn: Option<TurnConfig>,
|
||||||
|
|
||||||
pub emergency_password: Option<String>,
|
pub emergency_password: Option<String>,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
|
@ -95,6 +93,22 @@ pub struct TlsConfig {
|
||||||
pub key: String,
|
pub key: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
|
pub struct TurnConfig {
|
||||||
|
pub uris: Vec<String>,
|
||||||
|
#[serde(default = "default_turn_ttl")]
|
||||||
|
pub ttl: u64,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub auth: TurnAuth,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum TurnAuth {
|
||||||
|
UserPass { username: String, password: String },
|
||||||
|
Secret { secret: String },
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Default)]
|
#[derive(Clone, Debug, Deserialize, Default)]
|
||||||
pub struct WellKnownConfig {
|
pub struct WellKnownConfig {
|
||||||
#[serde(rename = "well_known_client")]
|
#[serde(rename = "well_known_client")]
|
||||||
|
@ -103,7 +117,14 @@ pub struct WellKnownConfig {
|
||||||
pub server: Option<OwnedServerName>,
|
pub server: Option<OwnedServerName>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEPRECATED_KEYS: &[&str] = &["cache_capacity"];
|
const DEPRECATED_KEYS: &[&str] = &[
|
||||||
|
"cache_capacity",
|
||||||
|
"turn_username",
|
||||||
|
"turn_password",
|
||||||
|
"turn_uris",
|
||||||
|
"turn_secret",
|
||||||
|
"turn_ttl",
|
||||||
|
];
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn warn_deprecated(&self) {
|
pub fn warn_deprecated(&self) {
|
||||||
|
@ -146,6 +167,32 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn turn(&self) -> Option<TurnConfig> {
|
||||||
|
if self.turn.is_some() {
|
||||||
|
self.turn.clone()
|
||||||
|
} else if let Some(uris) = self.turn_uris.clone() {
|
||||||
|
if let Some(secret) = self.turn_secret.clone() {
|
||||||
|
Some(TurnConfig {
|
||||||
|
uris,
|
||||||
|
ttl: self.turn_ttl,
|
||||||
|
auth: TurnAuth::Secret { secret },
|
||||||
|
})
|
||||||
|
} else if let (Some(username), Some(password)) =
|
||||||
|
(self.turn_username.clone(), self.turn_password.clone())
|
||||||
|
{
|
||||||
|
Some(TurnConfig {
|
||||||
|
uris,
|
||||||
|
ttl: self.turn_ttl,
|
||||||
|
auth: TurnAuth::UserPass { username, password },
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Config {
|
impl fmt::Display for Config {
|
||||||
|
@ -201,36 +248,17 @@ impl fmt::Display for Config {
|
||||||
}
|
}
|
||||||
&lst.join(", ")
|
&lst.join(", ")
|
||||||
}),
|
}),
|
||||||
(
|
("TURN URIs", {
|
||||||
"TURN username",
|
if let Some(turn) = self.turn() {
|
||||||
if self.turn_username.is_empty() {
|
|
||||||
"not set"
|
|
||||||
} else {
|
|
||||||
&self.turn_username
|
|
||||||
},
|
|
||||||
),
|
|
||||||
("TURN password", {
|
|
||||||
if self.turn_password.is_empty() {
|
|
||||||
"not set"
|
|
||||||
} else {
|
|
||||||
"set"
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
("TURN secret", {
|
|
||||||
if self.turn_secret.is_empty() {
|
|
||||||
"not set"
|
|
||||||
} else {
|
|
||||||
"set"
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
("Turn TTL", &self.turn_ttl.to_string()),
|
|
||||||
("Turn URIs", {
|
|
||||||
let mut lst = vec![];
|
let mut lst = vec![];
|
||||||
for item in self.turn_uris.iter().cloned().enumerate() {
|
for item in turn.uris.iter().cloned().enumerate() {
|
||||||
let (_, uri): (usize, String) = item;
|
let (_, uri): (usize, String) = item;
|
||||||
lst.push(uri);
|
lst.push(uri);
|
||||||
}
|
}
|
||||||
&lst.join(", ")
|
&lst.join(", ")
|
||||||
|
} else {
|
||||||
|
"unset"
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
("Well-known server name", well_known_server.as_str()),
|
("Well-known server name", well_known_server.as_str()),
|
||||||
("Well-known client URL", &self.well_known_client()),
|
("Well-known client URL", &self.well_known_client()),
|
||||||
|
|
|
@ -7,7 +7,7 @@ use ruma::{
|
||||||
|
|
||||||
use crate::api::server_server::DestinationResponse;
|
use crate::api::server_server::DestinationResponse;
|
||||||
|
|
||||||
use crate::{services, Config, Error, Result};
|
use crate::{config::TurnConfig, services, Config, Error, Result};
|
||||||
use futures_util::FutureExt;
|
use futures_util::FutureExt;
|
||||||
use hickory_resolver::TokioAsyncResolver;
|
use hickory_resolver::TokioAsyncResolver;
|
||||||
use hyper_util::client::legacy::connect::dns::{GaiResolver, Name as HyperName};
|
use hyper_util::client::legacy::connect::dns::{GaiResolver, Name as HyperName};
|
||||||
|
@ -348,6 +348,10 @@ impl Service {
|
||||||
&self.config.trusted_servers
|
&self.config.trusted_servers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn turn(&self) -> Option<TurnConfig> {
|
||||||
|
self.config.turn()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn dns_resolver(&self) -> &TokioAsyncResolver {
|
pub fn dns_resolver(&self) -> &TokioAsyncResolver {
|
||||||
&self.dns_resolver
|
&self.dns_resolver
|
||||||
}
|
}
|
||||||
|
@ -356,26 +360,6 @@ impl Service {
|
||||||
self.jwt_decoding_key.as_ref()
|
self.jwt_decoding_key.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn turn_password(&self) -> &String {
|
|
||||||
&self.config.turn_password
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn turn_ttl(&self) -> u64 {
|
|
||||||
self.config.turn_ttl
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn turn_uris(&self) -> &[String] {
|
|
||||||
&self.config.turn_uris
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn turn_username(&self) -> &String {
|
|
||||||
&self.config.turn_username
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn turn_secret(&self) -> &String {
|
|
||||||
&self.config.turn_secret
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn emergency_password(&self) -> &Option<String> {
|
pub fn emergency_password(&self) -> &Option<String> {
|
||||||
&self.config.emergency_password
|
&self.config.emergency_password
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue