Skip to main content

oxpulse_sfu_kit/
dc.rs

1//! DataChannel configuration wrappers.
2//!
3//! Provides a thin, semver-stable façade over [`str0m::channel::ChannelConfig`]
4//! and [`str0m::channel::Reliability`] so callers never import from `str0m`
5//! directly for DataChannel configuration.
6//!
7//! # Usage
8//!
9//! ```rust
10//! use oxpulse_sfu_kit::ChannelConfig;
11//!
12//! let chat   = ChannelConfig::reliable_ordered();
13//! let ctrl   = ChannelConfig::unreliable_max_retransmits(0);
14//! let voice  = ChannelConfig::unreliable_max_lifetime(200);
15//! ```
16
17/// Stable configuration descriptor for a DataChannel pre-registration.
18///
19/// One `ChannelConfig` is pushed into the client's DC list by every
20/// `with_extra_dc` / `with_chat_dcs` / `with_voice_dc` call.
21/// The SFU application (e.g. `partner-edge`) reads these out via
22/// [`Client::extra_dcs()`][crate::Client::extra_dcs] during
23/// offer/answer negotiation and passes them to `Rtc::open_stream`.
24///
25/// # Invariant
26///
27/// Exactly one of `max_packet_lifetime_ms` and `max_retransmits` is `Some`
28/// for unreliable channels; both are `None` for reliable channels.
29/// Both being `Some` simultaneously is undefined behaviour in str0m.
30/// The three constructors enforce this; constructing `ChannelConfig` via
31/// struct literal outside this module is not possible (fields are
32/// `pub(crate)`).
33#[derive(Debug, Clone, PartialEq, Eq)]
34pub struct ChannelConfig {
35    /// SCTP stream identifier. Must be unique per peer-connection.
36    pub(crate) id: u16,
37    /// Human-readable channel label (e.g. `"chat-data"`, `"voice"`).
38    pub(crate) label: String,
39    /// Whether in-order delivery is required.
40    pub(crate) ordered: bool,
41    /// Maximum packet lifetime in milliseconds.
42    ///
43    /// Maps to [`str0m::channel::Reliability::MaxPacketLifetime`].
44    /// `None` = use retransmit policy or reliable delivery.
45    ///
46    /// Stored as `u32` for range parity with the spec contract.
47    /// Note: str0m's internal `Reliability::MaxPacketLifetime.lifetime`
48    /// is `u16`; callers converting to str0m must `try_into::<u16>()`.
49    pub(crate) max_packet_lifetime_ms: Option<u32>,
50    /// Maximum number of retransmits before the packet is discarded.
51    ///
52    /// Maps to [`str0m::channel::Reliability::MaxRetransmits`].
53    /// `None` = use lifetime or reliable delivery.
54    pub(crate) max_retransmits: Option<u16>,
55}
56
57impl ChannelConfig {
58    /// Reliable, ordered DataChannel (TCP-like semantics).
59    ///
60    /// Used by `with_chat_dcs` for the `"chat-data"` channel (id=4).
61    #[must_use]
62    pub fn reliable_ordered() -> Self {
63        Self {
64            id: 0,
65            label: String::new(),
66            ordered: true,
67            max_packet_lifetime_ms: None,
68            max_retransmits: None,
69        }
70    }
71
72    /// Unordered, unreliable DataChannel with a max-retransmit count.
73    ///
74    /// Pass `retransmits = 0` for fire-and-forget semantics.
75    /// Used by `with_chat_dcs` for the `"chat-ctrl"` channel (id=5).
76    #[must_use]
77    pub fn unreliable_max_retransmits(retransmits: u16) -> Self {
78        Self {
79            id: 0,
80            label: String::new(),
81            ordered: false,
82            max_packet_lifetime_ms: None,
83            max_retransmits: Some(retransmits),
84        }
85    }
86
87    /// Unordered, unreliable DataChannel with a max-packet-lifetime in milliseconds.
88    ///
89    /// Maps to [`str0m::channel::Reliability::MaxPacketLifetime`].
90    /// Used by `with_voice_dc` for low-latency voice data signalling (id=6).
91    ///
92    /// Note: str0m's internal representation uses `u16`; callers converting to
93    /// str0m must `try_into::<u16>()` on the stored value.
94    #[must_use]
95    pub fn unreliable_max_lifetime(lifetime_ms: u32) -> Self {
96        Self {
97            id: 0,
98            label: String::new(),
99            ordered: false,
100            max_packet_lifetime_ms: Some(lifetime_ms),
101            max_retransmits: None,
102        }
103    }
104
105    /// SCTP stream identifier. Must be unique per peer-connection.
106    #[must_use]
107    pub fn id(&self) -> u16 {
108        self.id
109    }
110
111    /// Human-readable channel label (e.g. `"chat-data"`, `"voice"`).
112    #[must_use]
113    pub fn label(&self) -> &str {
114        &self.label
115    }
116
117    /// Whether in-order delivery is required.
118    #[must_use]
119    pub fn ordered(&self) -> bool {
120        self.ordered
121    }
122
123    /// Maximum packet lifetime in milliseconds, if set.
124    ///
125    /// `Some` only for unreliable channels using `Reliability::MaxPacketLifetime`.
126    /// Mutually exclusive with [`max_retransmits`][Self::max_retransmits].
127    #[must_use]
128    pub fn max_packet_lifetime_ms(&self) -> Option<u32> {
129        self.max_packet_lifetime_ms
130    }
131
132    /// Maximum number of retransmits before discarding, if set.
133    ///
134    /// `Some` only for unreliable channels using `Reliability::MaxRetransmits`.
135    /// Mutually exclusive with [`max_packet_lifetime_ms`][Self::max_packet_lifetime_ms].
136    #[must_use]
137    pub fn max_retransmits(&self) -> Option<u16> {
138        self.max_retransmits
139    }
140}