use std::net::SocketAddr;
use std::sync::Arc;
use tokio::sync::Mutex;
use tracing::{debug, error, info, warn};
use crate::api::common::error::SecurityError;
use crate::dtls::DtlsConnection;
use crate::srtp::SrtpContext;
use crate::api::client::security::srtp::keys;
use crate::dtls::record::{Record, ContentType};
use crate::dtls::message::handshake::HandshakeHeader;
pub async fn process_packet(
data: &[u8],
connection: &Arc<Mutex<Option<DtlsConnection>>>,
remote_addr: &Arc<Mutex<Option<SocketAddr>>>,
handshake_completed: &Arc<Mutex<bool>>,
srtp_context: &Arc<Mutex<Option<SrtpContext>>>,
) -> Result<(), SecurityError> {
debug!("Client received packet of {} bytes - delegating to DTLS library", data.len());
if data.len() >= 1 && (data[0] == 20 || data[0] == 22) {
return process_dtls_packet(data, connection, remote_addr, handshake_completed, srtp_context).await;
}
let mut conn_guard = connection.lock().await;
if let Some(conn) = conn_guard.as_mut() {
if let Err(e) = conn.process_packet(data).await {
warn!("Error processing packet: {}", e);
return Err(SecurityError::HandshakeError(format!("Failed to process packet: {}", e)));
}
Ok(())
} else {
Err(SecurityError::NotInitialized("DTLS connection not initialized".to_string()))
}
}
pub async fn process_dtls_packet(
data: &[u8],
connection: &Arc<Mutex<Option<DtlsConnection>>>,
remote_addr: &Arc<Mutex<Option<SocketAddr>>>,
handshake_completed: &Arc<Mutex<bool>>,
srtp_context: &Arc<Mutex<Option<SrtpContext>>>,
) -> Result<(), SecurityError> {
debug!("Client received {} bytes from server", data.len());
let mut conn_guard = connection.lock().await;
if let Some(conn) = conn_guard.as_mut() {
if data.len() >= 14 && data[0] == 22 && data[13] == 3 {
debug!("Detected HelloVerifyRequest packet, will handle specially");
if let Err(e) = conn.process_packet(data).await {
debug!("Error processing HelloVerifyRequest: {}", e);
return Err(SecurityError::HandshakeError(format!("Failed to process HelloVerifyRequest: {}", e)));
}
let remote_addr_guard = remote_addr.lock().await;
if let Some(addr) = *remote_addr_guard {
if conn.handshake_step() == Some(crate::dtls::handshake::HandshakeStep::ReceivedHelloVerifyRequest) {
debug!("Continuing handshake after HelloVerifyRequest");
if let Err(e) = conn.continue_handshake().await {
warn!("Failed to continue handshake with cookie: {}", e);
return Err(SecurityError::HandshakeError(format!("Failed to continue handshake with cookie: {}", e)));
} else {
debug!("Successfully continued handshake with cookie");
}
} else {
debug!("Restarting handshake with cookie");
if let Err(e) = conn.start_handshake(addr).await {
warn!("Failed to restart handshake with cookie: {}", e);
return Err(SecurityError::HandshakeError(format!("Failed to restart handshake with cookie: {}", e)));
} else {
debug!("Successfully restarted handshake with cookie");
}
}
}
return Ok(());
}
if let Err(e) = conn.process_packet(data).await {
debug!("Error processing DTLS packet: {}", e);
return Err(SecurityError::HandshakeError(format!("Failed to process DTLS packet: {}", e)));
}
if let Some(step) = conn.handshake_step() {
debug!("Current handshake step: {:?}", step);
match step {
crate::dtls::handshake::HandshakeStep::ReceivedServerHello => {
debug!("Received ServerHello");
if let Err(e) = conn.continue_handshake().await {
warn!("Failed to continue handshake after ServerHello: {}", e);
return Err(SecurityError::HandshakeError(format!("Failed to continue handshake: {}", e)));
} else {
debug!("Successfully continued handshake after ServerHello");
}
},
crate::dtls::handshake::HandshakeStep::SentClientKeyExchange => {
debug!("Sent ClientKeyExchange");
if let Err(e) = conn.complete_handshake().await {
warn!("Failed to complete handshake: {}", e);
return Err(SecurityError::HandshakeError(format!("Failed to complete handshake: {}", e)));
} else {
debug!("Successfully completed handshake");
}
},
crate::dtls::handshake::HandshakeStep::Complete => {
debug!("Handshake complete");
let mut completed = handshake_completed.lock().await;
if !*completed {
*completed = true;
if conn.state() == crate::dtls::connection::ConnectionState::Connected {
drop(conn_guard);
if let Err(e) = keys::extract_srtp_keys(connection, srtp_context, handshake_completed).await {
warn!("Failed to extract SRTP keys: {}", e);
return Err(e);
}
info!("DTLS handshake completed and SRTP keys extracted");
}
}
},
_ => {} }
}
Ok(())
} else {
Err(SecurityError::NotInitialized("DTLS connection not initialized".to_string()))
}
}
pub async fn handle_hello_verify_request(
connection: &Arc<Mutex<Option<DtlsConnection>>>,
remote_addr: &Option<SocketAddr>,
) -> Result<(), SecurityError> {
let addr = match remote_addr {
Some(addr) => *addr,
None => return Err(SecurityError::Configuration("Remote address not set".to_string())),
};
let mut conn_guard = connection.lock().await;
if let Some(conn) = conn_guard.as_mut() {
if conn.handshake_step() == Some(crate::dtls::handshake::HandshakeStep::ReceivedHelloVerifyRequest) {
debug!("Handling HelloVerifyRequest, restarting handshake with cookie");
if let Err(e) = conn.start_handshake(addr).await {
warn!("Failed to restart handshake with cookie: {}", e);
return Err(SecurityError::HandshakeError(format!("Failed to restart handshake with cookie: {}", e)));
}
debug!("Successfully restarted handshake with cookie");
Ok(())
} else {
debug!("Not in ReceivedHelloVerifyRequest state, cannot handle");
Err(SecurityError::HandshakeError("Not in ReceivedHelloVerifyRequest state".to_string()))
}
} else {
Err(SecurityError::NotInitialized("DTLS connection not initialized".to_string()))
}
}