use std::net::IpAddr;
use std::sync::Arc;
use crypto::RTCCryptoProvider;
use dtls::cipher_suite::CipherSuiteId;
use dtls::extension::extension_use_srtp::SrtpProtectionProfile;
use ice::network_type::NetworkType;
use crate::peer_connection::transport::dtls::role::RTCDtlsRole;
use crate::peer_connection::transport::ice::candidate_type::RTCIceCandidateType;
use ice::mdns::MulticastDnsMode;
use std::time::Duration;
pub(crate) const RECEIVE_MTU: usize = 1460;
#[derive(Default, Clone)]
pub struct Timeout {
pub ice_disconnected_timeout: Option<Duration>,
pub ice_failed_timeout: Option<Duration>,
pub ice_keepalive_interval: Option<Duration>,
pub ice_check_interval: Option<Duration>,
pub ice_max_binding_requests: Option<u16>,
pub ice_host_acceptance_min_wait: Option<Duration>,
pub ice_srflx_acceptance_min_wait: Option<Duration>,
pub ice_prflx_acceptance_min_wait: Option<Duration>,
pub ice_relay_acceptance_min_wait: Option<Duration>,
}
#[derive(Clone)]
pub struct DataChannel {
pub dcep_handshake_timeout: Option<Duration>,
}
impl Default for DataChannel {
fn default() -> Self {
Self {
dcep_handshake_timeout: Some(Duration::from_secs(30)),
}
}
}
#[derive(Clone)]
pub struct MulticastDNS {
pub timeout: Option<Duration>,
pub mode: MulticastDnsMode,
pub local_name: String,
pub local_ip: Option<IpAddr>,
}
impl Default for MulticastDNS {
fn default() -> Self {
Self {
timeout: Some(Duration::from_secs(10)),
mode: MulticastDnsMode::QueryOnly,
local_name: "".to_string(),
local_ip: None,
}
}
}
#[derive(Default, Clone)]
pub struct Candidates {
pub ice_lite: bool,
pub ice_network_types: Vec<NetworkType>,
pub nat_1to1_ips: Vec<String>,
pub nat_1to1_ip_candidate_type: RTCIceCandidateType,
pub username_fragment: String,
pub password: String,
pub discard_local_candidates_during_ice_restart: bool,
pub include_loopback_candidate: bool,
}
#[derive(Default, Copy, Clone)]
pub struct ReplayProtection {
pub dtls: usize,
pub srtp: usize,
pub srtcp: usize,
}
#[derive(Copy, Clone)]
#[non_exhaustive]
pub enum SctpMaxMessageSize {
Bounded(u32),
Unbounded,
}
impl SctpMaxMessageSize {
pub const DEFAULT_MESSAGE_SIZE: u32 = 65536;
pub const MAX_MESSAGE_SIZE: u32 = 262144;
pub fn as_usize(&self) -> usize {
match self {
Self::Bounded(result) => (*result).min(Self::MAX_MESSAGE_SIZE) as usize,
Self::Unbounded => Self::MAX_MESSAGE_SIZE as usize,
}
}
}
impl Default for SctpMaxMessageSize {
fn default() -> Self {
Self::Bounded(Self::DEFAULT_MESSAGE_SIZE)
}
}
#[derive(Default, Clone)]
pub struct SettingEngine {
pub(crate) crypto_provider: Option<Arc<dyn RTCCryptoProvider>>,
pub(crate) timeout: Timeout,
pub(crate) data_channel: DataChannel,
pub(crate) turn_allocation_refresh_interval_cap: Option<Duration>,
pub(crate) candidates: Candidates,
pub(crate) multicast_dns: MulticastDNS,
pub(crate) replay_protection: ReplayProtection,
pub(crate) sdp_media_level_fingerprints: bool,
pub(crate) answering_dtls_role: RTCDtlsRole,
pub(crate) disable_certificate_fingerprint_verification: bool,
pub(crate) allow_insecure_verification_algorithm: bool,
pub(crate) disable_media_engine_copy: bool,
pub(crate) disable_media_engine_multiple_codecs: bool,
pub(crate) srtp_protection_profiles: Vec<SrtpProtectionProfile>,
pub(crate) dtls_cipher_suites: Vec<CipherSuiteId>,
pub(crate) receive_mtu: usize,
pub(crate) mid_generator: Option<Arc<dyn Fn(isize) -> String + Send + Sync>>,
pub(crate) sctp_max_message_size: SctpMaxMessageSize,
pub(crate) sctp_max_receive_buffer_size: Option<u32>,
pub(crate) sctp_mtu: Option<u32>,
pub(crate) ignore_rid_pause_for_recv: bool,
pub(crate) write_ssrc_attributes_for_simulcast: bool,
}
impl SettingEngine {
pub fn crypto_provider(&self) -> Option<&Arc<dyn RTCCryptoProvider>> {
self.crypto_provider.as_ref()
}
#[doc(hidden)]
pub fn set_crypto_provider(&mut self, crypto_provider: Arc<dyn RTCCryptoProvider>) {
self.crypto_provider = Some(crypto_provider);
}
pub fn multicast_dns(&self) -> &MulticastDNS {
&self.multicast_dns
}
pub fn turn_allocation_refresh_interval_cap(&self) -> Option<Duration> {
self.turn_allocation_refresh_interval_cap
}
pub fn discard_local_candidates_during_ice_restart(&self) -> bool {
self.candidates.discard_local_candidates_during_ice_restart
}
}
#[derive(Default)]
pub struct SettingEngineBuilder(SettingEngine);
impl SettingEngineBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn with_crypto_provider(mut self, provider: Arc<dyn RTCCryptoProvider>) -> Self {
self.0.crypto_provider = Some(provider);
self
}
pub fn with_srtp_protection_profiles(mut self, profiles: Vec<SrtpProtectionProfile>) -> Self {
self.0.srtp_protection_profiles = profiles;
self
}
pub fn with_dtls_cipher_suites(mut self, cipher_suites: Vec<CipherSuiteId>) -> Self {
self.0.dtls_cipher_suites = cipher_suites;
self
}
pub fn with_turn_allocation_refresh_interval_cap(mut self, cap: Duration) -> Self {
self.0.turn_allocation_refresh_interval_cap = Some(cap);
self
}
pub fn with_ice_timeouts(
mut self,
disconnected_timeout: Option<Duration>,
failed_timeout: Option<Duration>,
keep_alive_interval: Option<Duration>,
) -> Self {
self.0.timeout.ice_disconnected_timeout = disconnected_timeout;
self.0.timeout.ice_failed_timeout = failed_timeout;
self.0.timeout.ice_keepalive_interval = keep_alive_interval;
self
}
pub fn with_dcep_handshake_timeout(mut self, timeout: Option<Duration>) -> Self {
self.0.data_channel.dcep_handshake_timeout = timeout;
self
}
pub fn with_ice_connection_attempts(
mut self,
check_interval: Option<Duration>,
max_binding_requests: Option<u16>,
) -> Self {
self.0.timeout.ice_check_interval = check_interval;
self.0.timeout.ice_max_binding_requests = max_binding_requests;
self
}
pub fn with_host_acceptance_min_wait(mut self, t: Option<Duration>) -> Self {
self.0.timeout.ice_host_acceptance_min_wait = t;
self
}
pub fn with_srflx_acceptance_min_wait(mut self, t: Option<Duration>) -> Self {
self.0.timeout.ice_srflx_acceptance_min_wait = t;
self
}
pub fn with_prflx_acceptance_min_wait(mut self, t: Option<Duration>) -> Self {
self.0.timeout.ice_prflx_acceptance_min_wait = t;
self
}
pub fn with_relay_acceptance_min_wait(mut self, t: Option<Duration>) -> Self {
self.0.timeout.ice_relay_acceptance_min_wait = t;
self
}
pub fn with_lite(mut self, lite: bool) -> Self {
self.0.candidates.ice_lite = lite;
self
}
pub fn with_network_types(mut self, candidate_types: Vec<NetworkType>) -> Self {
self.0.candidates.ice_network_types = candidate_types;
self
}
pub fn with_nat_1to1_ips(
mut self,
ips: Vec<String>,
candidate_type: RTCIceCandidateType,
) -> Self {
self.0.candidates.nat_1to1_ips = ips;
self.0.candidates.nat_1to1_ip_candidate_type = candidate_type;
self
}
pub fn with_answering_dtls_role(mut self, role: RTCDtlsRole) -> Self {
self.0.answering_dtls_role = role;
self
}
pub fn with_multicast_dns_timeout(mut self, timeout: Option<Duration>) -> Self {
self.0.multicast_dns.timeout = timeout;
self
}
pub fn with_multicast_dns_mode(mut self, multicast_dns_mode: MulticastDnsMode) -> Self {
self.0.multicast_dns.mode = multicast_dns_mode;
self
}
pub fn with_multicast_dns_local_name(mut self, local_name: String) -> Self {
self.0.multicast_dns.local_name = local_name;
self
}
pub fn with_multicast_dns_local_ip(mut self, local_ip: Option<IpAddr>) -> Self {
self.0.multicast_dns.local_ip = local_ip;
self
}
pub fn with_ice_credentials(mut self, username_fragment: String, password: String) -> Self {
self.0.candidates.username_fragment = username_fragment;
self.0.candidates.password = password;
self
}
pub fn with_disable_certificate_fingerprint_verification(mut self, is_disabled: bool) -> Self {
self.0.disable_certificate_fingerprint_verification = is_disabled;
self
}
pub fn with_allow_insecure_verification_algorithm(mut self, is_allowed: bool) -> Self {
self.0.allow_insecure_verification_algorithm = is_allowed;
self
}
pub fn with_dtls_replay_protection_window(mut self, n: usize) -> Self {
self.0.replay_protection.dtls = n;
self
}
pub fn with_srtp_replay_protection_window(mut self, n: usize) -> Self {
self.0.replay_protection.srtp = n;
self
}
pub fn with_srtcp_replay_protection_window(mut self, n: usize) -> Self {
self.0.replay_protection.srtcp = n;
self
}
pub fn with_include_loopback_candidate(mut self, allow_loopback: bool) -> Self {
self.0.candidates.include_loopback_candidate = allow_loopback;
self
}
pub fn with_discard_local_candidates_during_ice_restart(mut self, discard: bool) -> Self {
self.0
.candidates
.discard_local_candidates_during_ice_restart = discard;
self
}
pub fn with_sdp_media_level_fingerprints(mut self, sdp_media_level_fingerprints: bool) -> Self {
self.0.sdp_media_level_fingerprints = sdp_media_level_fingerprints;
self
}
pub fn with_disable_media_engine_copy(mut self, is_disabled: bool) -> Self {
self.0.disable_media_engine_copy = is_disabled;
self
}
pub fn with_disable_media_engine_multiple_codecs(mut self, is_disabled: bool) -> Self {
self.0.disable_media_engine_multiple_codecs = is_disabled;
self
}
pub fn with_receive_mtu(mut self, receive_mtu: usize) -> Self {
self.0.receive_mtu = receive_mtu;
self
}
pub fn with_mid_generator(
mut self,
f: impl Fn(isize) -> String + Send + Sync + 'static,
) -> Self {
self.0.mid_generator = Some(Arc::new(f));
self
}
pub fn with_sctp_max_message_size(mut self, max_message_size: SctpMaxMessageSize) -> Self {
self.0.sctp_max_message_size = max_message_size;
self
}
pub fn with_sctp_max_receive_buffer_size(mut self, size: u32) -> Self {
const MIN_SCTP_RECEIVE_BUFFER_SIZE: u32 = 1500;
if size < MIN_SCTP_RECEIVE_BUFFER_SIZE {
log::warn!(
"sctp receive buffer size {size} is below the RFC 4960 minimum; raising to \
{MIN_SCTP_RECEIVE_BUFFER_SIZE} bytes"
);
}
self.0.sctp_max_receive_buffer_size = Some(size.max(MIN_SCTP_RECEIVE_BUFFER_SIZE));
self
}
pub fn with_sctp_mtu(mut self, mtu: u32) -> Self {
self.0.sctp_mtu = Some(mtu);
self
}
pub fn with_ignore_rid_pause_for_recv(mut self, ignore_rid_pause_for_recv: bool) -> Self {
self.0.ignore_rid_pause_for_recv = ignore_rid_pause_for_recv;
self
}
pub fn with_write_ssrc_attributes_for_simulcast(
mut self,
write_ssrc_attributes_for_simulcast: bool,
) -> Self {
self.0.write_ssrc_attributes_for_simulcast = write_ssrc_attributes_for_simulcast;
self
}
pub fn build(self) -> SettingEngine {
self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_multicast_dns_mode_is_query_only() {
assert_eq!(MulticastDNS::default().mode, MulticastDnsMode::QueryOnly);
assert_eq!(
SettingEngine::default().multicast_dns.mode,
MulticastDnsMode::QueryOnly
);
}
#[test]
fn test_turn_allocation_refresh_interval_cap() {
assert_eq!(
SettingEngine::default().turn_allocation_refresh_interval_cap(),
None
);
let cap = Duration::from_secs(30);
let setting_engine = SettingEngineBuilder::new()
.with_turn_allocation_refresh_interval_cap(cap)
.build();
assert_eq!(
setting_engine.turn_allocation_refresh_interval_cap(),
Some(cap)
);
}
}