use crate::ids::{BridgeId, ConnectionId};
use dashmap::DashMap;
use std::hash::Hash;
use std::sync::Arc;
pub use rvoip_media_core::relay::controller::{BridgeError, BridgeHandle};
pub mod cross_handle;
pub mod frame_pump;
pub use cross_handle::CrossBridgeHandle;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct DirectionalMediaBridgePlan {
a_to_b: bool,
b_to_a: bool,
}
impl DirectionalMediaBridgePlan {
pub fn new(a_to_b: bool, b_to_a: bool) -> crate::Result<Self> {
if !a_to_b && !b_to_a {
return Err(crate::RvoipError::AdmissionRejected(
"media bridge must enable at least one direction",
));
}
Ok(Self { a_to_b, b_to_a })
}
#[must_use]
pub const fn bidirectional() -> Self {
Self {
a_to_b: true,
b_to_a: true,
}
}
#[must_use]
pub const fn a_to_b(self) -> bool {
self.a_to_b
}
#[must_use]
pub const fn b_to_a(self) -> bool {
self.b_to_a
}
}
pub fn codec_to_pt(name: &str) -> Option<u8> {
match name.to_ascii_lowercase().as_str() {
"pcmu" | "g.711-mu" | "g711-mu" | "g711-u" => Some(0),
"pcma" | "g.711-a" | "g711-a" => Some(8),
"g729" | "g.729" => Some(18),
"opus" => Some(111),
"pcm_s16le" | "pcm-s16le" => Some(rvoip_media_core::codec::audio::payload_type::PCM_S16LE),
_ => None,
}
}
#[cfg(test)]
mod codec_mapping_tests {
use super::codec_to_pt;
use rvoip_media_core::codec::audio::payload_type::PCM_S16LE;
#[test]
fn maps_internal_pcm_name_to_reserved_key() {
assert_eq!(codec_to_pt("pcm_s16le"), Some(PCM_S16LE));
assert_eq!(codec_to_pt("PCM_S16LE"), Some(PCM_S16LE));
assert_eq!(PCM_S16LE, 120);
}
}
pub struct BridgeManager<K = ConnectionId, I = BridgeId>
where
K: Eq + Hash + Clone,
I: Eq + Hash + Clone,
{
bridges: Arc<DashMap<I, (BridgeHandle, K)>>,
by_owner: Arc<DashMap<K, I>>,
}
impl<K, I> Clone for BridgeManager<K, I>
where
K: Eq + Hash + Clone,
I: Eq + Hash + Clone,
{
fn clone(&self) -> Self {
Self {
bridges: Arc::clone(&self.bridges),
by_owner: Arc::clone(&self.by_owner),
}
}
}
impl<K, I> Default for BridgeManager<K, I>
where
K: Eq + Hash + Clone,
I: Eq + Hash + Clone,
{
fn default() -> Self {
Self::new()
}
}
impl<K, I> BridgeManager<K, I>
where
K: Eq + Hash + Clone,
I: Eq + Hash + Clone,
{
pub fn new() -> Self {
Self {
bridges: Arc::new(DashMap::new()),
by_owner: Arc::new(DashMap::new()),
}
}
pub fn insert(&self, bridge_id: I, owner: K, handle: BridgeHandle) {
self.by_owner.insert(owner.clone(), bridge_id.clone());
self.bridges.insert(bridge_id, (handle, owner));
}
pub fn remove(&self, bridge_id: &I) -> Option<BridgeHandle> {
let (_, (handle, owner)) = self.bridges.remove(bridge_id)?;
self.by_owner
.remove_if(&owner, |_, registered| registered == bridge_id);
Some(handle)
}
pub fn bridge_for_owner(&self, owner: &K) -> Option<I> {
self.by_owner.get(owner).map(|entry| entry.value().clone())
}
pub fn len(&self) -> usize {
self.bridges.len()
}
pub fn is_empty(&self) -> bool {
self.bridges.is_empty()
}
}