use actr_protocol::PayloadType;
use std::time::Duration;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct RetryPolicy {
pub(crate) max_attempts: u32,
pub(crate) initial_delay: Duration,
pub(crate) max_delay: Duration,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) enum DataChannelQoS {
Signal,
Reliable,
LatencyFirst,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) enum DataLaneType {
WebRtcDataChannel(DataChannelQoS),
WebSocket,
}
pub(crate) trait PayloadTypeExt {
fn data_lane_types(self) -> &'static [DataLaneType];
fn retry_policy(self) -> RetryPolicy;
}
impl PayloadTypeExt for PayloadType {
#[inline]
fn retry_policy(self) -> RetryPolicy {
match self {
PayloadType::RpcSignal => RetryPolicy {
max_attempts: 2,
initial_delay: Duration::from_millis(500),
max_delay: Duration::from_millis(500),
},
PayloadType::RpcReliable => RetryPolicy {
max_attempts: 5,
initial_delay: Duration::from_secs(1),
max_delay: Duration::from_secs(5),
},
PayloadType::StreamReliable
| PayloadType::StreamLatencyFirst
| PayloadType::MediaRtp => RetryPolicy {
max_attempts: 1,
initial_delay: Duration::ZERO,
max_delay: Duration::ZERO,
},
}
}
#[inline]
fn data_lane_types(self) -> &'static [DataLaneType] {
match self {
PayloadType::RpcReliable => &[
DataLaneType::WebRtcDataChannel(DataChannelQoS::Reliable),
DataLaneType::WebSocket,
],
PayloadType::RpcSignal => &[
DataLaneType::WebRtcDataChannel(DataChannelQoS::Signal),
DataLaneType::WebSocket,
],
PayloadType::StreamReliable => &[
DataLaneType::WebRtcDataChannel(DataChannelQoS::Reliable),
DataLaneType::WebSocket,
],
PayloadType::StreamLatencyFirst => &[
DataLaneType::WebRtcDataChannel(DataChannelQoS::LatencyFirst),
DataLaneType::WebSocket,
],
PayloadType::MediaRtp => &[],
}
}
}
impl DataLaneType {
#[inline]
pub(crate) fn needs_webrtc(self) -> bool {
matches!(self, DataLaneType::WebRtcDataChannel(_))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rpc_signal_retry_policy() {
let p = PayloadType::RpcSignal.retry_policy();
assert_eq!(p.max_attempts, 2, "one retry only");
assert_eq!(p.initial_delay, Duration::from_millis(500));
assert_eq!(p.max_delay, Duration::from_millis(500));
}
#[test]
fn rpc_reliable_retry_policy() {
let p = PayloadType::RpcReliable.retry_policy();
assert_eq!(p.max_attempts, 5, "four retries");
assert_eq!(p.initial_delay, Duration::from_secs(1));
assert_eq!(p.max_delay, Duration::from_secs(5));
}
#[test]
fn stream_and_media_no_retry() {
for pt in [
PayloadType::StreamReliable,
PayloadType::StreamLatencyFirst,
PayloadType::MediaRtp,
] {
let p = pt.retry_policy();
assert_eq!(p.max_attempts, 1, "{pt:?} should have no retry");
}
}
#[test]
fn rpc_reliable_lane_types() {
let lanes = PayloadType::RpcReliable.data_lane_types();
assert!(lanes.contains(&DataLaneType::WebRtcDataChannel(DataChannelQoS::Reliable)));
assert!(lanes.contains(&DataLaneType::WebSocket));
}
#[test]
fn rpc_signal_lane_types() {
let lanes = PayloadType::RpcSignal.data_lane_types();
assert!(lanes.contains(&DataLaneType::WebRtcDataChannel(DataChannelQoS::Signal)));
}
#[test]
fn media_rtp_has_no_lane() {
assert!(PayloadType::MediaRtp.data_lane_types().is_empty());
}
}