use async_trait::async_trait;
use std::any::Any;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::net::UdpSocket;
use crate::api::common::config::{SecurityInfo, SecurityMode, SrtpProfile};
use crate::api::common::error::SecurityError;
pub mod client;
pub mod core;
pub mod default;
pub mod dtls;
pub mod srtp;
pub mod util;
pub use client::context::DefaultClientSecurityContext;
pub use default::DefaultServerSecurityContext;
#[derive(Clone)]
pub struct SocketHandle {
pub socket: Arc<UdpSocket>,
pub remote_addr: Option<SocketAddr>,
}
#[derive(Clone)]
pub struct ConnectionConfig {
pub role: ConnectionRole,
pub srtp_profiles: Vec<SrtpProfile>,
pub fingerprint_algorithm: String,
pub certificate_path: Option<String>,
pub private_key_path: Option<String>,
}
impl Default for ConnectionConfig {
fn default() -> Self {
Self {
role: ConnectionRole::Server,
srtp_profiles: vec![SrtpProfile::AesCm128HmacSha1_80, SrtpProfile::AesGcm128],
fingerprint_algorithm: "sha-256".to_string(),
certificate_path: None,
private_key_path: None,
}
}
}
#[derive(Clone)]
pub enum ConnectionRole {
Client,
Server,
}
#[derive(Debug, Clone)]
pub struct ServerSecurityConfig {
pub security_mode: SecurityMode,
pub fingerprint_algorithm: String,
pub certificate_path: Option<String>,
pub private_key_path: Option<String>,
pub srtp_profiles: Vec<SrtpProfile>,
pub require_client_certificate: bool,
pub srtp_key: Option<Vec<u8>>,
}
impl Default for ServerSecurityConfig {
fn default() -> Self {
Self {
security_mode: SecurityMode::DtlsSrtp,
fingerprint_algorithm: "sha-256".to_string(),
certificate_path: None,
private_key_path: None,
srtp_profiles: vec![SrtpProfile::AesCm128HmacSha1_80, SrtpProfile::AesGcm128],
require_client_certificate: false,
srtp_key: None,
}
}
}
#[async_trait]
pub trait ClientSecurityContext: Send + Sync {
async fn set_socket(&self, socket: SocketHandle) -> Result<(), SecurityError>;
async fn get_remote_fingerprint(&self) -> Result<Option<String>, SecurityError>;
async fn get_fingerprint(&self) -> Result<String, SecurityError>;
async fn get_fingerprint_algorithm(&self) -> Result<String, SecurityError>;
async fn close(&self) -> Result<(), SecurityError>;
fn is_secure(&self) -> bool;
fn get_security_info(&self) -> SecurityInfo;
async fn wait_for_handshake(&self) -> Result<(), SecurityError>;
async fn is_handshake_complete(&self) -> Result<bool, SecurityError>;
async fn process_dtls_packet(&self, data: &[u8]) -> Result<(), SecurityError>;
async fn start_handshake_with_remote(
&self,
remote_addr: SocketAddr,
) -> Result<(), SecurityError>;
fn as_any(&self) -> &dyn Any;
}
#[async_trait]
pub trait ServerSecurityContext: Send + Sync {
async fn initialize(&self) -> Result<(), SecurityError>;
async fn set_socket(&self, socket: SocketHandle) -> Result<(), SecurityError>;
async fn get_fingerprint(&self) -> Result<String, SecurityError>;
async fn get_fingerprint_algorithm(&self) -> Result<String, SecurityError>;
async fn start_listening(&self) -> Result<(), SecurityError>;
async fn stop_listening(&self) -> Result<(), SecurityError>;
async fn start_packet_handler(&self) -> Result<(), SecurityError>;
async fn capture_initial_packet(&self) -> Result<Option<(Vec<u8>, SocketAddr)>, SecurityError>;
async fn create_client_context(
&self,
addr: SocketAddr,
) -> Result<Arc<dyn ClientSecurityContext + Send + Sync>, SecurityError>;
async fn get_client_contexts(&self) -> Vec<Arc<dyn ClientSecurityContext + Send + Sync>>;
async fn remove_client(&self, addr: SocketAddr) -> Result<(), SecurityError>;
async fn on_client_secure(
&self,
callback: Box<dyn Fn(Arc<dyn ClientSecurityContext + Send + Sync>) + Send + Sync>,
) -> Result<(), SecurityError>;
async fn get_supported_srtp_profiles(&self) -> Vec<SrtpProfile>;
fn is_secure(&self) -> bool;
fn get_security_info(&self) -> SecurityInfo;
async fn process_client_packet(
&self,
addr: SocketAddr,
data: &[u8],
) -> Result<(), SecurityError>;
async fn is_ready(&self) -> Result<bool, SecurityError>;
fn get_config(&self) -> &ServerSecurityConfig;
}
pub async fn new(
config: ServerSecurityConfig,
) -> Result<Arc<dyn ServerSecurityContext + Send + Sync>, SecurityError> {
match config.security_mode {
SecurityMode::Srtp => {
let srtp_ctx = srtp::SrtpServerSecurityContext::new(config).await?;
Ok(srtp_ctx as Arc<dyn ServerSecurityContext + Send + Sync>)
}
SecurityMode::DtlsSrtp => {
let dtls_ctx = DefaultServerSecurityContext::new(config).await?;
Ok(dtls_ctx as Arc<dyn ServerSecurityContext + Send + Sync>)
}
SecurityMode::SdesSrtp | SecurityMode::MikeySrtp | SecurityMode::ZrtpSrtp => {
let dtls_ctx = DefaultServerSecurityContext::new(config).await?;
Ok(dtls_ctx as Arc<dyn ServerSecurityContext + Send + Sync>)
}
SecurityMode::None => {
let dtls_ctx = DefaultServerSecurityContext::new(config).await?;
Ok(dtls_ctx as Arc<dyn ServerSecurityContext + Send + Sync>)
}
}
}