use dashmap::{DashMap, DashSet};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum RtcMessage {
Offer {
from: Uuid,
to: Uuid,
sdp: String,
#[serde(default, skip_serializing_if = "serde_json::Value::is_null")]
meta: serde_json::Value,
},
Answer {
from: Uuid,
to: Uuid,
sdp: String,
#[serde(default, skip_serializing_if = "serde_json::Value::is_null")]
meta: serde_json::Value,
},
Candidate {
from: Uuid,
to: Uuid,
candidate: String,
},
CandidateBatch {
from: Uuid,
to: Uuid,
candidates: Vec<String>,
},
Status {
from: Uuid,
to: Uuid,
status: String,
},
PeerList {
peers: Vec<Uuid>,
},
PeerDiscovery {
#[serde(default, skip_serializing_if = "Option::is_none")]
room: Option<String>,
},
TurnCredentials(TurnCredential),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TurnCredential {
pub username: String,
pub credential: String,
pub ttl_seconds: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub server: Option<String>,
}
#[derive(Debug, Default)]
pub struct RtcRouter {
seen_candidates: DashMap<(Uuid, Uuid), DashSet<String>>,
}
impl RtcRouter {
pub fn new() -> Self {
Self {
seen_candidates: DashMap::new(),
}
}
pub fn dedup_candidate(&self, from: Uuid, to: Uuid, candidate: &str) -> bool {
let set = self.seen_candidates.entry((from, to)).or_default();
set.insert(candidate.to_string())
}
pub fn dedup_batch(&self, from: Uuid, to: Uuid, candidates: Vec<String>) -> Vec<String> {
candidates
.into_iter()
.filter(|c| self.dedup_candidate(from, to, c))
.collect()
}
}