use rvoip_rtp_core::api::common::{
config::{KeyExchangeMethod, SecurityConfig, SecurityMode},
security_manager::{NegotiationStrategy, SecurityContextManager},
unified_security::SecurityContextFactory,
};
use std::fmt;
use std::time::Duration;
use tracing::{info, warn};
const MAX_RUNTIME_SECONDS: u64 = 8;
#[derive(Debug)]
struct ExampleError(String);
impl fmt::Display for ExampleError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl std::error::Error for ExampleError {}
impl From<Box<dyn std::error::Error + Send + Sync>> for ExampleError {
fn from(err: Box<dyn std::error::Error + Send + Sync>) -> Self {
ExampleError(err.to_string())
}
}
#[tokio::main]
async fn main() -> Result<(), ExampleError> {
tracing_subscriber::fmt()
.with_max_level(tracing::Level::INFO)
.init();
let _timeout_handle = tokio::spawn(async {
tokio::time::sleep(Duration::from_secs(MAX_RUNTIME_SECONDS)).await;
warn!("Example timeout reached - this is normal for a demo");
std::process::exit(0);
});
info!("🚀 Unified Security API Example");
info!("===============================");
info!("Demonstrating Phase 1: Non-DTLS SRTP & Authentication Schemes");
info!("");
demo_security_configurations().await?;
demo_unified_security_context().await?;
demo_security_context_manager().await?;
demo_key_exchange_properties().await?;
info!("✅ All demos completed successfully!");
info!("🎯 Phase 1 infrastructure is ready for Phase 2 protocol implementations");
Ok(())
}
async fn demo_security_configurations() -> Result<(), ExampleError> {
info!("📋 Demo 1: Security Configuration Showcase");
info!("------------------------------------------");
info!("🔧 Traditional configurations:");
let webrtc_config = SecurityConfig::webrtc_compatible();
info!(" WebRTC: {:?} mode", webrtc_config.mode);
let basic_srtp = SecurityConfig::srtp_with_key(generate_test_key());
info!(" Basic SRTP: {:?} mode", basic_srtp.mode);
info!("🆕 New SIP-derived configurations:");
let sdes_config = SecurityConfig::sdes_srtp();
info!(
" SDES-SRTP: {:?} mode (SDP key exchange)",
sdes_config.mode
);
let mikey_config = SecurityConfig::mikey_psk();
info!(
" MIKEY-SRTP: {:?} mode (enterprise key mgmt)",
mikey_config.mode
);
let zrtp_config = SecurityConfig::zrtp_p2p();
info!(
" ZRTP-SRTP: {:?} mode (P2P secure calling)",
zrtp_config.mode
);
info!("🏢 Predefined SIP scenario configurations:");
let enterprise = SecurityConfig::sip_enterprise();
info!(" Enterprise: {:?} mode", enterprise.mode);
let operator = SecurityConfig::sip_operator();
info!(" Operator: {:?} mode", operator.mode);
let p2p = SecurityConfig::sip_peer_to_peer();
info!(" P2P: {:?} mode", p2p.mode);
let bridge = SecurityConfig::sip_webrtc_bridge();
info!(" SIP↔WebRTC: {:?} mode", bridge.mode);
let multi_method = SecurityConfig::multi_method(vec![
KeyExchangeMethod::Sdes,
KeyExchangeMethod::DtlsSrtp,
KeyExchangeMethod::PreSharedKey,
]);
info!(
" Multi-method: {:?} mode (with fallback)",
multi_method.mode
);
info!("✅ Configuration showcase complete");
info!("");
Ok(())
}
async fn demo_unified_security_context() -> Result<(), ExampleError> {
info!("🔐 Demo 2: Unified Security Context");
info!("-----------------------------------");
info!("Creating security contexts for different methods...");
info!("📊 Testing Pre-Shared Key (PSK) context:");
let psk_context = SecurityContextFactory::create_psk_context(generate_test_key())
.map_err(|e| ExampleError(format!("Failed to create PSK context: {}", e)))?;
info!(" Method: {:?}", psk_context.get_method());
info!(" State: {:?}", psk_context.get_state().await);
psk_context
.initialize()
.await
.map_err(|e| ExampleError(format!("Failed to initialize PSK context: {}", e)))?;
info!(" After initialization:");
info!(" State: {:?}", psk_context.get_state().await);
info!(" Ready: {}", psk_context.is_established().await);
info!("📊 Testing SDES context:");
let sdes_context = SecurityContextFactory::create_sdes_context()
.map_err(|e| ExampleError(format!("Failed to create SDES context: {}", e)))?;
info!(" Method: {:?}", sdes_context.get_method());
info!(" State: {:?}", sdes_context.get_state().await);
sdes_context
.initialize()
.await
.map_err(|e| ExampleError(format!("Failed to initialize SDES context: {}", e)))?;
info!(" After initialization:");
info!(" State: {:?}", sdes_context.get_state().await);
info!(" Ready: {}", sdes_context.is_established().await);
info!("📊 Key exchange method properties:");
let methods = vec![
KeyExchangeMethod::DtlsSrtp,
KeyExchangeMethod::Sdes,
KeyExchangeMethod::Mikey,
KeyExchangeMethod::Zrtp,
KeyExchangeMethod::PreSharedKey,
];
for method in methods {
info!(" {:?}:", method);
info!(
" Network exchange: {}",
method.requires_network_exchange()
);
info!(" Signaling based: {}", method.uses_signaling_exchange());
info!(" Media path: {}", method.uses_media_exchange());
}
info!("✅ Unified security context demo complete");
info!("");
Ok(())
}
async fn demo_security_context_manager() -> Result<(), ExampleError> {
info!("🎛️ Demo 3: Security Context Manager");
info!("------------------------------------");
let config = SecurityConfig::srtp_with_key(generate_test_key());
let manager = SecurityContextManager::new(config);
info!("Created SecurityContextManager");
info!("Active method: {:?}", manager.get_active_method().await);
info!("Initializing security contexts...");
manager
.initialize()
.await
.map_err(|e| ExampleError(format!("Failed to initialize manager: {}", e)))?;
let available_methods = manager.list_available_methods().await;
info!("Available methods: {:?}", available_methods);
let capabilities = manager.get_capabilities().await;
info!("Security capabilities:");
info!(" Supported methods: {:?}", capabilities.supported_methods);
info!(" Can offer: {}", capabilities.can_offer);
info!(" Can answer: {}", capabilities.can_answer);
info!(
" SRTP profiles: {} supported",
capabilities.srtp_profiles.len()
);
info!("Testing auto-negotiation strategies:");
if let Ok(method) = manager
.auto_negotiate(NegotiationStrategy::FirstAvailable)
.await
{
info!(" FirstAvailable: {:?}", method);
info!(" Active method: {:?}", manager.get_active_method().await);
let is_established = manager.is_established().await.unwrap_or(false);
info!(" Security established: {}", is_established);
}
info!("Testing signaling method detection:");
let test_signals = vec![
(
"SDES SDP",
b"a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:test" as &[u8],
),
("MIKEY", b"MIKEY v1.0 message"),
("ZRTP", b"zrtp-version: 1.10"),
("Unknown", b"random signaling data"),
];
for (name, _signal) in test_signals {
info!(
" {}: Would be auto-detected as SDES/MIKEY/ZRTP based on content",
name
);
}
info!("✅ Security context manager demo complete");
info!("");
Ok(())
}
async fn demo_key_exchange_properties() -> Result<(), ExampleError> {
info!("🔄 Demo 4: Key Exchange Method Properties");
info!("-----------------------------------------");
info!("Security mode ↔ Key exchange method conversions:");
let modes = vec![
SecurityMode::None,
SecurityMode::Srtp,
SecurityMode::DtlsSrtp,
SecurityMode::SdesSrtp,
SecurityMode::MikeySrtp,
SecurityMode::ZrtpSrtp,
];
for mode in modes {
if let Some(method) = mode.key_exchange_method() {
let back_to_mode = method.to_security_mode();
info!(" {:?} → {:?} → {:?}", mode, method, back_to_mode);
} else {
info!(" {:?} → No key exchange", mode);
}
}
info!("Security mode properties:");
for mode in [
SecurityMode::None,
SecurityMode::Srtp,
SecurityMode::DtlsSrtp,
SecurityMode::SdesSrtp,
SecurityMode::MikeySrtp,
SecurityMode::ZrtpSrtp,
] {
info!(" {:?}:", mode);
info!(" Enabled: {}", mode.is_enabled());
info!(" Requires SRTP: {}", mode.requires_srtp());
}
info!("Protocol compatibility matrix:");
info!(" Method | WebRTC | SIP/SDP | Enterprise | P2P");
info!(" --------------|--------|---------|------------|----");
info!(" DTLS-SRTP | ✅ | ❓ | ❓ | ❓");
info!(" SDES-SRTP | ❓ | ✅ | ✅ | ❓");
info!(" MIKEY-SRTP | ❌ | ✅ | ✅ | ❌");
info!(" ZRTP-SRTP | ❓ | ✅ | ❓ | ✅");
info!(" PSK-SRTP | ❌ | ❌ | ✅ | ❌");
info!("");
info!(" ✅ = Excellent fit");
info!(" ❓ = Possible but not ideal");
info!(" ❌ = Not suitable");
info!("✅ Key exchange properties demo complete");
info!("");
Ok(())
}
fn generate_test_key() -> Vec<u8> {
vec![
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E,
]
}