Skip to main content

o_sfu_protocol/
host_bridge.rs

1use std::{borrow::Cow, collections::BTreeMap};
2
3use serde::{Serialize, Serializer};
4
5use crate::{
6    bundle_api::{
7        BundleBroadcastUpdate, BundleDisconnectUpdate, BundleRemoteMediaUpdate,
8        BundleSessionInfoSnapshotById, BundleUpdate, bundle_session_info_key,
9    },
10    core::ProtocolEvent,
11    shared::{JsonPayload, RecordingStateUpdate, UserId, UserInfo},
12    signaling::TrackBinding,
13};
14
15#[derive(Serialize)]
16#[serde(tag = "name", content = "payload", rename_all = "snake_case")]
17enum BundleUpdateRef<'a> {
18    RemoteMedia {
19        bindings: &'a [TrackBinding],
20    },
21    Broadcast {
22        #[serde(rename = "senderId")]
23        sender_id: &'a UserId,
24        message: &'a JsonPayload,
25    },
26    Disconnect {
27        #[serde(rename = "sessionId")]
28        user_id: &'a UserId,
29    },
30    #[serde(rename = "info_change")]
31    SessionInfoChange(BTreeMap<Cow<'a, str>, &'a UserInfo>),
32    ChannelInfoChange(&'a RecordingStateUpdate),
33}
34
35#[must_use]
36pub fn project_protocol_event(event: ProtocolEvent) -> BundleUpdate {
37    match event {
38        ProtocolEvent::TrackSnapshot { bindings } => {
39            BundleUpdate::RemoteMedia(BundleRemoteMediaUpdate { bindings })
40        }
41        ProtocolEvent::PeerSnapshot { peers } => BundleUpdate::SessionInfoChange(
42            peers
43                .into_iter()
44                .map(|peer| (bundle_session_info_key(&peer.user_id), peer.info))
45                .collect::<BundleSessionInfoSnapshotById>(),
46        ),
47        ProtocolEvent::PeerInfo { user_id, info } => BundleUpdate::SessionInfoChange(
48            BundleSessionInfoSnapshotById::from([(bundle_session_info_key(&user_id), info)]),
49        ),
50        ProtocolEvent::PeerLeft { user_id } => {
51            BundleUpdate::Disconnect(BundleDisconnectUpdate { user_id })
52        }
53        ProtocolEvent::Broadcast { sender_id, message } => {
54            BundleUpdate::Broadcast(BundleBroadcastUpdate { sender_id, message })
55        }
56        ProtocolEvent::RecordingStateChanged { state } => BundleUpdate::ChannelInfoChange(state),
57    }
58}
59
60pub(crate) fn serialize_protocol_event<S>(
61    event: &ProtocolEvent,
62    serializer: S,
63) -> Result<S::Ok, S::Error>
64where
65    S: Serializer,
66{
67    let update = match event {
68        ProtocolEvent::TrackSnapshot { bindings } => BundleUpdateRef::RemoteMedia { bindings },
69        ProtocolEvent::PeerSnapshot { peers } => BundleUpdateRef::SessionInfoChange(
70            peers
71                .iter()
72                .map(|peer| (peer.user_id.path_segment(), &peer.info))
73                .collect(),
74        ),
75        ProtocolEvent::PeerInfo { user_id, info } => {
76            BundleUpdateRef::SessionInfoChange(BTreeMap::from([(user_id.path_segment(), info)]))
77        }
78        ProtocolEvent::PeerLeft { user_id } => BundleUpdateRef::Disconnect { user_id },
79        ProtocolEvent::Broadcast { sender_id, message } => {
80            BundleUpdateRef::Broadcast { sender_id, message }
81        }
82        ProtocolEvent::RecordingStateChanged { state } => BundleUpdateRef::ChannelInfoChange(state),
83    };
84    update.serialize(serializer)
85}
86
87#[cfg(test)]
88#[path = "host_bridge/TESTS/mod.rs"]
89mod tests;