use anyhow::{Context, Result};
use serde::Deserialize;
use std::path::Path;
use tokio::fs;
#[derive(Debug, Deserialize, Clone)]
pub struct Config {
pub addr: Option<String>,
pub external_ip: Option<String>,
pub recorders: Option<String>,
pub accounts: Vec<AccountConfig>,
}
impl Config {
pub async fn load(path: impl AsRef<Path>) -> Result<Self> {
let content = fs::read_to_string(path)
.await
.context("Failed to read config file")?;
let config: Config = toml::from_str(&content).context("Failed to parse config file")?;
Ok(config)
}
}
#[derive(Debug, Deserialize, Clone, Default)]
pub struct AccountConfig {
pub username: String,
pub auth_username: Option<String>,
pub domain: String,
pub password: Option<String>,
pub proxy: Option<String>,
pub register: Option<bool>, pub target: Option<String>, pub record: Option<String>, pub srtp_enabled: Option<bool>, pub nack_enabled: Option<bool>, pub jitter_buffer_enabled: Option<bool>, pub reject_prob: Option<u8>, pub codecs: Option<Vec<String>>, pub headers: Option<Vec<String>>, #[serde(default)]
pub cancel_prob: u8,
pub early_media: Option<EarlyMediaConfig>,
pub ring: Option<RingConfig>,
pub answer: Option<AnswerConfig>,
pub hangup: Option<HangupConfig>,
pub refer_reject: Option<u16>, }
#[derive(Debug, Deserialize, Clone)]
pub struct EarlyMediaConfig {
pub wav_file: Option<String>,
pub local: Option<bool>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct RingConfig {
pub duration_secs: u64,
pub ringback: Option<String>, pub local: Option<bool>,
}
#[derive(Debug, Deserialize, Clone)]
#[serde(tag = "action", rename_all = "snake_case")]
pub enum AnswerConfig {
Play { wav_file: String },
Echo,
Local,
}
#[derive(Debug, Deserialize, Clone)]
pub struct HangupConfig {
pub code: u16, pub after_secs: Option<u64>, }