use chrono::{DateTime, Utc};
use tokio::sync::mpsc;
use tokio::task::AbortHandle;
use super::frame_pump::TranscoderSwap;
use crate::error::{Result, RvoipError};
use crate::ids::{BridgeId, ConnectionId};
pub struct CrossBridgeHandle {
pub id: BridgeId,
pub a: ConnectionId,
pub b: ConnectionId,
pub created_at: DateTime<Utc>,
a_to_b: AbortHandle,
b_to_a: AbortHandle,
swap_a_to_b: Option<mpsc::Sender<TranscoderSwap>>,
swap_b_to_a: Option<mpsc::Sender<TranscoderSwap>>,
}
impl CrossBridgeHandle {
pub fn new(
id: BridgeId,
a: ConnectionId,
b: ConnectionId,
a_to_b: AbortHandle,
b_to_a: AbortHandle,
) -> Self {
Self {
id,
a,
b,
created_at: Utc::now(),
a_to_b,
b_to_a,
swap_a_to_b: None,
swap_b_to_a: None,
}
}
pub fn with_swap_channels(
id: BridgeId,
a: ConnectionId,
b: ConnectionId,
a_to_b: AbortHandle,
b_to_a: AbortHandle,
swap_a_to_b: mpsc::Sender<TranscoderSwap>,
swap_b_to_a: mpsc::Sender<TranscoderSwap>,
) -> Self {
Self {
id,
a,
b,
created_at: Utc::now(),
a_to_b,
b_to_a,
swap_a_to_b: Some(swap_a_to_b),
swap_b_to_a: Some(swap_b_to_a),
}
}
pub async fn swap_transcoders(
&self,
mut a_to_b_swap: TranscoderSwap,
mut b_to_a_swap: TranscoderSwap,
) -> Result<()> {
let Some(a_tx) = self.swap_a_to_b.as_ref() else {
return Err(RvoipError::NotImplemented(
"CrossBridgeHandle::swap_transcoders — bridge built without swap channels",
));
};
let Some(b_tx) = self.swap_b_to_a.as_ref() else {
return Err(RvoipError::NotImplemented(
"CrossBridgeHandle::swap_transcoders — bridge built without swap channels",
));
};
let (a_ack_tx, a_ack_rx) = tokio::sync::oneshot::channel();
let (b_ack_tx, b_ack_rx) = tokio::sync::oneshot::channel();
a_to_b_swap.ack = Some(a_ack_tx);
b_to_a_swap.ack = Some(b_ack_tx);
let a_send_ok = a_tx.send(a_to_b_swap).await.is_ok();
let b_send_ok = b_tx.send(b_to_a_swap).await.is_ok();
let to = std::time::Duration::from_secs(1);
if a_send_ok {
let _ = tokio::time::timeout(to, a_ack_rx).await;
}
if b_send_ok {
let _ = tokio::time::timeout(to, b_ack_rx).await;
}
Ok(())
}
}
impl Drop for CrossBridgeHandle {
fn drop(&mut self) {
self.a_to_b.abort();
self.b_to_a.abort();
}
}