Skip to main content

pushwire_core/
rtc.rs

1use dashmap::{DashMap, DashSet};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5/// RTC signaling messages carried on the `rtc` channel.
6#[derive(Debug, Clone, Serialize, Deserialize)]
7#[serde(tag = "type", rename_all = "snake_case")]
8pub enum RtcMessage {
9    Offer {
10        from: Uuid,
11        to: Uuid,
12        sdp: String,
13        #[serde(default, skip_serializing_if = "serde_json::Value::is_null")]
14        meta: serde_json::Value,
15    },
16    Answer {
17        from: Uuid,
18        to: Uuid,
19        sdp: String,
20        #[serde(default, skip_serializing_if = "serde_json::Value::is_null")]
21        meta: serde_json::Value,
22    },
23    Candidate {
24        from: Uuid,
25        to: Uuid,
26        candidate: String,
27    },
28    CandidateBatch {
29        from: Uuid,
30        to: Uuid,
31        candidates: Vec<String>,
32    },
33    Status {
34        from: Uuid,
35        to: Uuid,
36        status: String,
37    },
38    PeerList {
39        peers: Vec<Uuid>,
40    },
41    PeerDiscovery {
42        #[serde(default, skip_serializing_if = "Option::is_none")]
43        room: Option<String>,
44    },
45    TurnCredentials(TurnCredential),
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct TurnCredential {
50    pub username: String,
51    pub credential: String,
52    pub ttl_seconds: u64,
53    #[serde(default, skip_serializing_if = "Option::is_none")]
54    pub server: Option<String>,
55}
56
57#[derive(Debug, Default)]
58pub struct RtcRouter {
59    /// Per (from,to) deduplication set for candidates to avoid floods.
60    seen_candidates: DashMap<(Uuid, Uuid), DashSet<String>>,
61}
62
63impl RtcRouter {
64    pub fn new() -> Self {
65        Self {
66            seen_candidates: DashMap::new(),
67        }
68    }
69
70    pub fn dedup_candidate(&self, from: Uuid, to: Uuid, candidate: &str) -> bool {
71        let set = self.seen_candidates.entry((from, to)).or_default();
72        set.insert(candidate.to_string())
73    }
74
75    pub fn dedup_batch(&self, from: Uuid, to: Uuid, candidates: Vec<String>) -> Vec<String> {
76        candidates
77            .into_iter()
78            .filter(|c| self.dedup_candidate(from, to, c))
79            .collect()
80    }
81}