1use crate::media::depacketizer::{DefaultDepacketizerFactory, DepacketizerFactory};
2use serde::{Deserialize, Serialize};
3use std::fmt::{Debug, Formatter};
4use std::sync::Arc;
5
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
8#[serde(rename_all = "lowercase")]
9pub enum IceCredentialType {
10 #[default]
11 Password,
12 Oauth,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
17pub struct IceServer {
18 pub urls: Vec<String>,
19 pub username: Option<String>,
20 pub credential: Option<String>,
21 #[serde(default)]
22 pub credential_type: IceCredentialType,
23}
24
25impl IceServer {
26 pub fn new<T: Into<Vec<String>>>(urls: T) -> Self {
27 Self {
28 urls: urls.into(),
29 username: None,
30 credential: None,
31 credential_type: IceCredentialType::default(),
32 }
33 }
34
35 pub fn with_credential(
36 mut self,
37 username: impl Into<String>,
38 credential: impl Into<String>,
39 ) -> Self {
40 self.username = Some(username.into());
41 self.credential = Some(credential.into());
42 self
43 }
44
45 pub fn credential_type(mut self, kind: IceCredentialType) -> Self {
46 self.credential_type = kind;
47 self
48 }
49}
50
51impl Default for IceServer {
52 fn default() -> Self {
53 Self::new(Vec::new())
54 }
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
58pub enum IceTransportPolicy {
59 #[default]
60 All,
61 Relay,
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
66pub enum IceTcpPolicy {
67 #[default]
69 Disabled,
70 Enabled,
72 PassiveOnly,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
77pub enum BundlePolicy {
78 #[default]
79 Balanced,
80 MaxCompat,
81 MaxBundle,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
85pub enum RtcpMuxPolicy {
86 #[default]
87 Require,
88 Negotiate,
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
92pub enum TransportMode {
93 #[default]
94 WebRtc,
95 Srtp,
96 Rtp,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
101pub enum BufferDropStrategy {
102 #[default]
103 DropNew,
104 DropOldest,
105}
106
107#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
109pub struct CertificateConfig {
110 pub pem_chain: Vec<String>,
111 pub private_key_pem: Option<String>,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
116pub struct AudioCapability {
117 pub payload_type: u8,
118 pub codec_name: String,
119 pub clock_rate: u32,
120 pub channels: u8,
121 pub fmtp: Option<String>,
122 pub rtcp_fbs: Vec<String>,
123}
124
125impl Default for AudioCapability {
126 fn default() -> Self {
127 Self {
128 payload_type: 111,
129 codec_name: "opus".to_string(),
130 clock_rate: 48000,
131 channels: 2,
132 fmtp: Some("minptime=10;useinbandfec=1;stereo=1".to_string()),
133 rtcp_fbs: vec![],
134 }
135 }
136}
137
138impl AudioCapability {
139 pub fn opus() -> Self {
140 Self::default()
141 }
142
143 pub fn pcmu() -> Self {
144 Self {
145 payload_type: 0,
146 codec_name: "PCMU".to_string(),
147 clock_rate: 8000,
148 channels: 1,
149 fmtp: None,
150 rtcp_fbs: vec![],
151 }
152 }
153
154 pub fn pcma() -> Self {
155 Self {
156 payload_type: 8,
157 codec_name: "PCMA".to_string(),
158 clock_rate: 8000,
159 channels: 1,
160 fmtp: None,
161 rtcp_fbs: vec![],
162 }
163 }
164
165 pub fn g722() -> Self {
166 Self {
167 payload_type: 9,
168 codec_name: "G722".to_string(),
169 clock_rate: 8000,
170 channels: 1,
171 fmtp: None,
172 rtcp_fbs: vec![],
173 }
174 }
175
176 pub fn g729() -> Self {
177 Self {
178 payload_type: 18,
179 codec_name: "G729".to_string(),
180 clock_rate: 8000,
181 channels: 1,
182 fmtp: None,
183 rtcp_fbs: vec![],
184 }
185 }
186
187 pub fn telephone_event() -> Self {
188 Self {
189 payload_type: 101,
190 codec_name: "telephone-event".to_string(),
191 clock_rate: 8000,
192 channels: 1,
193 fmtp: Some("0-16".to_string()),
194 rtcp_fbs: vec![],
195 }
196 }
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
200pub struct VideoCapability {
201 pub payload_type: u8,
202 pub codec_name: String,
203 pub clock_rate: u32,
204 pub fmtp: Option<String>,
205 pub rtcp_fbs: Vec<String>,
206}
207
208impl Default for VideoCapability {
209 fn default() -> Self {
210 Self {
211 payload_type: 96,
212 codec_name: "VP8".to_string(),
213 clock_rate: 90000,
214 fmtp: None,
215 rtcp_fbs: vec![
216 "nack".to_string(),
217 "nack pli".to_string(),
218 "ccm fir".to_string(),
219 "goog-remb".to_string(),
220 "transport-cc".to_string(),
221 ],
222 }
223 }
224}
225
226impl VideoCapability {
227 pub fn h264() -> Self {
228 Self {
229 payload_type: 96,
230 codec_name: "H264".to_string(),
231 clock_rate: 90000,
232 fmtp: Some("packetization-mode=1;profile-level-id=42e01f".to_string()),
233 rtcp_fbs: vec!["nack pli".to_string(), "ccm fir".to_string()],
234 }
235 }
236}
237
238#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
239pub struct ApplicationCapability {
240 pub sctp_port: u16,
241}
242
243impl Default for ApplicationCapability {
244 fn default() -> Self {
245 Self { sctp_port: 5000 }
246 }
247}
248
249#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
250pub enum T38FaxRateManagement {
251 #[serde(rename = "transferredTCF")]
252 TransferredTCF,
253 #[serde(rename = "localTCF")]
254 LocalTCF,
255}
256
257impl Default for T38FaxRateManagement {
258 fn default() -> Self {
259 Self::TransferredTCF
260 }
261}
262
263impl std::fmt::Display for T38FaxRateManagement {
264 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
265 match self {
266 Self::TransferredTCF => write!(f, "transferredTCF"),
267 Self::LocalTCF => write!(f, "localTCF"),
268 }
269 }
270}
271
272#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
273pub enum T38UdpEC {
274 #[serde(rename = "t38UDPRedundancy")]
275 T38UDPRedundancy,
276 #[serde(rename = "t38UDPFEC")]
277 T38UDPFEC,
278}
279
280impl Default for T38UdpEC {
281 fn default() -> Self {
282 Self::T38UDPRedundancy
283 }
284}
285
286impl std::fmt::Display for T38UdpEC {
287 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
288 match self {
289 Self::T38UDPRedundancy => write!(f, "t38UDPRedundancy"),
290 Self::T38UDPFEC => write!(f, "t38UDPFEC"),
291 }
292 }
293}
294
295#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
296pub struct T38Capability {
297 pub payload_type: u8,
298 pub version: u8,
300 pub max_bitrate: u32,
302 pub rate_management: T38FaxRateManagement,
304 pub max_buffer: u16,
306 pub max_datagram: u16,
308 pub udp_ec: T38UdpEC,
310 pub fmtp: Option<String>,
311}
312
313impl Default for T38Capability {
314 fn default() -> Self {
315 Self {
316 payload_type: 98,
317 version: 0,
318 max_bitrate: 14400,
319 rate_management: T38FaxRateManagement::default(),
320 max_buffer: 1024,
321 max_datagram: 238,
322 udp_ec: T38UdpEC::default(),
323 fmtp: None,
324 }
325 }
326}
327
328impl T38Capability {
329 pub fn default_t38() -> Self {
330 Self::default()
331 }
332}
333
334#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
335pub struct MediaCapabilities {
336 pub audio: Vec<AudioCapability>,
337 pub video: Vec<VideoCapability>,
338 pub application: Option<ApplicationCapability>,
339 pub image: Vec<T38Capability>,
340}
341
342impl Default for MediaCapabilities {
343 fn default() -> Self {
344 Self {
345 audio: vec![AudioCapability::opus(), AudioCapability::pcmu()],
346 video: vec![VideoCapability::default()],
347 application: Some(ApplicationCapability::default()),
348 image: vec![],
349 }
350 }
351}
352
353#[derive(Clone)]
354pub struct DepacketizerStrategy {
355 pub factory: Arc<dyn DepacketizerFactory>,
356}
357
358impl Default for DepacketizerStrategy {
359 fn default() -> Self {
360 Self {
361 factory: Arc::new(DefaultDepacketizerFactory),
362 }
363 }
364}
365
366impl Debug for DepacketizerStrategy {
367 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
368 self.factory.fmt(f)
369 }
370}
371
372impl PartialEq for DepacketizerStrategy {
373 fn eq(&self, other: &Self) -> bool {
374 Arc::ptr_eq(&self.factory, &other.factory)
375 }
376}
377
378impl Eq for DepacketizerStrategy {}
379
380fn default_rtp_buffer_capacity() -> usize {
381 100
382}
383
384fn default_buffer_stats_log_interval() -> std::time::Duration {
385 std::time::Duration::from_secs(10)
386}
387
388#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
390#[serde(rename_all = "snake_case")]
391pub enum SdpCompatibilityMode {
392 #[default]
394 Standard,
395 LegacySip,
398}
399
400fn default_enable_upnp() -> bool {
401 false
402}
403
404fn default_upnp_lease_duration() -> u32 {
405 3600
406}
407
408#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
410pub struct RtcConfiguration {
411 pub ice_servers: Vec<IceServer>,
412 pub ice_transport_policy: IceTransportPolicy,
413 pub bundle_policy: BundlePolicy,
414 pub rtcp_mux_policy: RtcpMuxPolicy,
415 pub certificates: Vec<CertificateConfig>,
416 pub transport_mode: TransportMode,
417 pub nack_buffer_size: usize,
418 pub media_capabilities: Option<MediaCapabilities>,
419 pub external_ip: Option<String>,
424 pub external_port: Option<u16>,
436 pub bind_ip: Option<String>,
437 pub disable_ipv6: bool,
438 pub ssrc_start: u32,
439 pub stun_timeout: std::time::Duration,
440 pub nomination_timeout: std::time::Duration,
444 pub ice_connection_timeout: std::time::Duration,
445 pub sctp_rto_initial: std::time::Duration,
446 pub sctp_rto_min: std::time::Duration,
447 pub sctp_rto_max: std::time::Duration,
448 pub sctp_max_association_retransmits: u32,
449 pub sctp_receive_window: usize,
450 pub sctp_heartbeat_interval: std::time::Duration,
451 pub sctp_max_heartbeat_failures: u32,
452 pub sctp_max_tsn_retransmits: u32,
453 pub sctp_max_burst: usize,
454 pub sctp_max_cwnd: usize,
455 pub dtls_buffer_size: usize,
456 pub rtp_start_port: Option<u16>,
457 pub rtp_end_port: Option<u16>,
458 pub ice_gather_udp_hosts: bool,
459 pub tcp_port_range_start: Option<u16>,
460 pub tcp_port_range_end: Option<u16>,
461 pub enable_latching: bool,
462 pub probation_max_packets: Option<u8>,
463 pub enable_ice_lite: bool,
464 #[serde(default)]
471 pub prefer_srflx_over_natted_host: bool,
472 #[serde(default = "default_enable_upnp")]
474 pub enable_upnp: bool,
475 #[serde(default = "default_upnp_lease_duration")]
477 pub upnp_lease_duration: u32,
478 #[serde(skip, default)]
479 pub depacketizer_strategy: DepacketizerStrategy,
480 #[serde(default = "default_rtp_buffer_capacity")]
481 pub rtp_buffer_capacity: usize,
482 #[serde(default)]
483 pub buffer_drop_strategy: BufferDropStrategy,
484 #[serde(default = "default_buffer_stats_log_interval")]
485 pub buffer_stats_log_interval: std::time::Duration,
486 #[serde(default)]
489 pub ice_tcp_policy: IceTcpPolicy,
490 #[serde(default)]
492 pub sdp_compatibility: SdpCompatibilityMode,
493 #[serde(skip, default)]
494 pub label: Option<String>,
495 #[serde(skip, default)]
496 pub cname: Option<String>,
497}
498
499impl Default for RtcConfiguration {
500 fn default() -> Self {
501 Self {
502 ice_servers: Vec::new(),
503 ice_transport_policy: IceTransportPolicy::default(),
504 bundle_policy: BundlePolicy::default(),
505 rtcp_mux_policy: RtcpMuxPolicy::default(),
506 certificates: Vec::new(),
507 transport_mode: TransportMode::default(),
508 nack_buffer_size: 200,
509 media_capabilities: None,
510 external_ip: None,
511 external_port: None,
512 bind_ip: None,
513 disable_ipv6: false,
514 ssrc_start: 10000,
515 stun_timeout: std::time::Duration::from_secs(5),
516 nomination_timeout: std::time::Duration::from_secs(10),
517 ice_connection_timeout: std::time::Duration::from_secs(30),
518 sctp_rto_initial: std::time::Duration::from_secs(3),
519 sctp_rto_min: std::time::Duration::from_secs(1),
520 sctp_rto_max: std::time::Duration::from_secs(60),
521 sctp_max_association_retransmits: 20,
522 sctp_receive_window: 128 * 1024, sctp_heartbeat_interval: std::time::Duration::from_secs(15),
524 sctp_max_heartbeat_failures: 4,
525 sctp_max_tsn_retransmits: 8,
526 sctp_max_burst: 0, sctp_max_cwnd: 256 * 1024, dtls_buffer_size: 2048,
529 rtp_start_port: None,
530 rtp_end_port: None,
531 ice_gather_udp_hosts: true,
532 tcp_port_range_start: None,
533 tcp_port_range_end: None,
534 enable_latching: false,
535 probation_max_packets: None,
536 enable_ice_lite: false,
537 prefer_srflx_over_natted_host: false,
538 enable_upnp: default_enable_upnp(),
539 upnp_lease_duration: default_upnp_lease_duration(),
540 depacketizer_strategy: DepacketizerStrategy::default(),
541 rtp_buffer_capacity: default_rtp_buffer_capacity(),
542 buffer_drop_strategy: BufferDropStrategy::default(),
543 buffer_stats_log_interval: default_buffer_stats_log_interval(),
544 ice_tcp_policy: IceTcpPolicy::default(),
545 sdp_compatibility: SdpCompatibilityMode::default(),
546 label: None,
547 cname: None,
548 }
549 }
550}
551
552pub struct RtcConfigurationBuilder {
553 inner: RtcConfiguration,
554}
555
556impl Default for RtcConfigurationBuilder {
557 fn default() -> Self {
558 Self::new()
559 }
560}
561
562impl RtcConfigurationBuilder {
563 pub fn new() -> Self {
564 Self {
565 inner: RtcConfiguration::default(),
566 }
567 }
568
569 pub fn enable_latching(mut self, enable: bool) -> Self {
570 self.inner.enable_latching = enable;
571 self
572 }
573
574 pub fn probation_max_packets(mut self, max: Option<u8>) -> Self {
575 self.inner.probation_max_packets = max;
576 self
577 }
578
579 pub fn enable_ice_lite(mut self, enable: bool) -> Self {
580 self.inner.enable_ice_lite = enable;
581 self
582 }
583
584 pub fn prefer_srflx_over_natted_host(mut self, enable: bool) -> Self {
585 self.inner.prefer_srflx_over_natted_host = enable;
586 self
587 }
588
589 pub fn enable_upnp(mut self, enable: bool) -> Self {
590 self.inner.enable_upnp = enable;
591 self
592 }
593
594 pub fn upnp_lease_duration(mut self, duration_secs: u32) -> Self {
595 self.inner.upnp_lease_duration = duration_secs;
596 self
597 }
598
599 pub fn ice_server(mut self, server: IceServer) -> Self {
600 self.inner.ice_servers.push(server);
601 self
602 }
603
604 pub fn ice_transport_policy(mut self, policy: IceTransportPolicy) -> Self {
605 self.inner.ice_transport_policy = policy;
606 self
607 }
608
609 pub fn bundle_policy(mut self, policy: BundlePolicy) -> Self {
610 self.inner.bundle_policy = policy;
611 self
612 }
613
614 pub fn rtcp_mux_policy(mut self, policy: RtcpMuxPolicy) -> Self {
615 self.inner.rtcp_mux_policy = policy;
616 self
617 }
618
619 pub fn certificate(mut self, cert: CertificateConfig) -> Self {
620 self.inner.certificates.push(cert);
621 self
622 }
623
624 pub fn transport_mode(mut self, mode: TransportMode) -> Self {
625 self.inner.transport_mode = mode;
626 self
627 }
628
629 pub fn media_capabilities(mut self, capabilities: MediaCapabilities) -> Self {
630 self.inner.media_capabilities = Some(capabilities);
631 self
632 }
633
634 pub fn external_ip(mut self, ip: String) -> Self {
635 self.inner.external_ip = Some(ip);
636 self
637 }
638
639 pub fn external_port(mut self, port: u16) -> Self {
640 self.inner.external_port = Some(port);
641 self
642 }
643
644 pub fn bind_ip(mut self, ip: String) -> Self {
645 self.inner.bind_ip = Some(ip);
646 self
647 }
648
649 pub fn disable_ipv6(mut self, disable: bool) -> Self {
650 self.inner.disable_ipv6 = disable;
651 self
652 }
653
654 pub fn ssrc_start(mut self, start: u32) -> Self {
655 self.inner.ssrc_start = start;
656 self
657 }
658
659 pub fn stun_timeout(mut self, timeout: std::time::Duration) -> Self {
660 self.inner.stun_timeout = timeout;
661 self
662 }
663
664 pub fn nomination_timeout(mut self, timeout: std::time::Duration) -> Self {
665 self.inner.nomination_timeout = timeout;
666 self
667 }
668
669 pub fn rtp_port_range(mut self, start: u16, end: u16) -> Self {
670 self.inner.rtp_start_port = Some(start);
671 self.inner.rtp_end_port = Some(end);
672 self
673 }
674
675 pub fn ice_gather_udp_hosts(mut self, enable: bool) -> Self {
676 self.inner.ice_gather_udp_hosts = enable;
677 self
678 }
679
680 pub fn tcp_port_range(mut self, start: u16, end: u16) -> Self {
681 self.inner.tcp_port_range_start = Some(start);
682 self.inner.tcp_port_range_end = Some(end);
683 self
684 }
685
686 pub fn dtls_buffer_size(mut self, size: usize) -> Self {
687 self.inner.dtls_buffer_size = size;
688 self
689 }
690
691 pub fn sctp_rto_initial(mut self, duration: std::time::Duration) -> Self {
692 self.inner.sctp_rto_initial = duration;
693 self
694 }
695
696 pub fn sctp_rto_min(mut self, duration: std::time::Duration) -> Self {
697 self.inner.sctp_rto_min = duration;
698 self
699 }
700
701 pub fn sctp_rto_max(mut self, duration: std::time::Duration) -> Self {
702 self.inner.sctp_rto_max = duration;
703 self
704 }
705
706 pub fn sctp_max_association_retransmits(mut self, count: u32) -> Self {
707 self.inner.sctp_max_association_retransmits = count;
708 self
709 }
710
711 pub fn sctp_receive_window(mut self, size: usize) -> Self {
712 self.inner.sctp_receive_window = size;
713 self
714 }
715
716 pub fn sctp_heartbeat_interval(mut self, duration: std::time::Duration) -> Self {
717 self.inner.sctp_heartbeat_interval = duration;
718 self
719 }
720
721 pub fn sctp_max_heartbeat_failures(mut self, count: u32) -> Self {
722 self.inner.sctp_max_heartbeat_failures = count;
723 self
724 }
725
726 pub fn sctp_max_burst(mut self, packets: usize) -> Self {
731 self.inner.sctp_max_burst = packets;
732 self
733 }
734
735 pub fn sctp_max_cwnd(mut self, size: usize) -> Self {
738 self.inner.sctp_max_cwnd = size;
739 self
740 }
741
742 pub fn ice_connection_timeout(mut self, timeout: std::time::Duration) -> Self {
743 self.inner.ice_connection_timeout = timeout;
744 self
745 }
746
747 pub fn rtp_buffer_capacity(mut self, capacity: usize) -> Self {
748 self.inner.rtp_buffer_capacity = capacity;
749 self
750 }
751
752 pub fn buffer_drop_strategy(mut self, strategy: BufferDropStrategy) -> Self {
753 self.inner.buffer_drop_strategy = strategy;
754 self
755 }
756
757 pub fn buffer_stats_log_interval(mut self, interval: std::time::Duration) -> Self {
758 self.inner.buffer_stats_log_interval = interval;
759 self
760 }
761
762 pub fn ice_tcp_policy(mut self, policy: IceTcpPolicy) -> Self {
763 self.inner.ice_tcp_policy = policy;
764 self
765 }
766
767 pub fn sdp_compatibility(mut self, mode: SdpCompatibilityMode) -> Self {
768 self.inner.sdp_compatibility = mode;
769 self
770 }
771
772 pub fn cname(mut self, cname: String) -> Self {
773 self.inner.cname = Some(cname);
774 self
775 }
776
777 pub fn build(self) -> RtcConfiguration {
778 self.inner
779 }
780}
781
782impl From<RtcConfigurationBuilder> for RtcConfiguration {
783 fn from(builder: RtcConfigurationBuilder) -> Self {
784 builder.build()
785 }
786}
787
788#[cfg(test)]
789mod tests {
790 use super::*;
791 use std::time::Duration;
792
793 #[test]
794 fn test_rtc_configuration_defaults() {
795 let config = RtcConfiguration::default();
796 assert_eq!(config.ice_connection_timeout, Duration::from_secs(30));
797 assert_eq!(config.sctp_rto_initial, Duration::from_secs(3));
798 assert_eq!(config.sctp_rto_min, Duration::from_secs(1));
799 assert_eq!(config.sctp_rto_max, Duration::from_secs(60));
800 assert_eq!(config.sctp_max_association_retransmits, 20);
801 assert_eq!(config.sctp_heartbeat_interval, Duration::from_secs(15));
802 assert_eq!(config.sctp_max_heartbeat_failures, 4);
803 assert_eq!(config.sctp_max_burst, 0);
804 assert_eq!(config.sctp_max_cwnd, 256 * 1024);
805 assert_eq!(config.rtp_buffer_capacity, 100);
806 assert_eq!(config.buffer_drop_strategy, BufferDropStrategy::DropNew);
807 assert_eq!(config.buffer_stats_log_interval, Duration::from_secs(10));
808 }
809
810 #[test]
811 fn test_rtc_configuration_builder() {
812 let config = RtcConfigurationBuilder::new()
813 .stun_timeout(Duration::from_secs(10))
814 .build();
815 assert_eq!(config.stun_timeout, Duration::from_secs(10));
816 assert_eq!(config.ice_connection_timeout, Duration::from_secs(30));
818 }
819
820 #[test]
821 fn test_buffer_config_builder() {
822 let config = RtcConfigurationBuilder::new()
823 .rtp_buffer_capacity(200)
824 .buffer_drop_strategy(BufferDropStrategy::DropOldest)
825 .buffer_stats_log_interval(Duration::from_secs(5))
826 .build();
827 assert_eq!(config.rtp_buffer_capacity, 200);
828 assert_eq!(config.buffer_drop_strategy, BufferDropStrategy::DropOldest);
829 assert_eq!(config.buffer_stats_log_interval, Duration::from_secs(5));
830 }
831
832 #[test]
833 fn test_sctp_builder_methods() {
834 let config = RtcConfigurationBuilder::new()
835 .sctp_rto_initial(Duration::from_millis(500))
836 .sctp_rto_min(Duration::from_millis(200))
837 .sctp_rto_max(Duration::from_secs(10))
838 .sctp_max_association_retransmits(30)
839 .sctp_receive_window(512 * 1024)
840 .sctp_heartbeat_interval(Duration::from_secs(10))
841 .sctp_max_heartbeat_failures(8)
842 .sctp_max_burst(4)
843 .sctp_max_cwnd(512 * 1024)
844 .ice_connection_timeout(Duration::from_secs(60))
845 .build();
846
847 assert_eq!(config.sctp_rto_initial, Duration::from_millis(500));
848 assert_eq!(config.sctp_rto_min, Duration::from_millis(200));
849 assert_eq!(config.sctp_rto_max, Duration::from_secs(10));
850 assert_eq!(config.sctp_max_association_retransmits, 30);
851 assert_eq!(config.sctp_receive_window, 512 * 1024);
852 assert_eq!(config.sctp_heartbeat_interval, Duration::from_secs(10));
853 assert_eq!(config.sctp_max_heartbeat_failures, 8);
854 assert_eq!(config.sctp_max_burst, 4);
855 assert_eq!(config.sctp_max_cwnd, 512 * 1024);
856 assert_eq!(config.ice_connection_timeout, Duration::from_secs(60));
857 }
858
859 #[test]
860 fn test_turn_optimized_config() {
861 let config = RtcConfigurationBuilder::new()
863 .sctp_rto_initial(Duration::from_millis(500))
864 .sctp_rto_min(Duration::from_millis(200))
865 .sctp_rto_max(Duration::from_secs(10))
866 .sctp_max_association_retransmits(30)
867 .sctp_max_heartbeat_failures(8)
868 .sctp_max_burst(4)
869 .stun_timeout(Duration::from_secs(10))
870 .nomination_timeout(Duration::from_secs(20))
871 .build();
872
873 let defaults = RtcConfiguration::default();
875 assert!(config.sctp_rto_initial < defaults.sctp_rto_initial);
876 assert!(config.sctp_rto_min < defaults.sctp_rto_min);
877 assert!(config.sctp_rto_max < defaults.sctp_rto_max);
878 assert!(
879 config.sctp_max_association_retransmits > defaults.sctp_max_association_retransmits
880 );
881 assert!(config.sctp_max_heartbeat_failures > defaults.sctp_max_heartbeat_failures);
882 assert!(config.sctp_max_burst > 0); }
884
885 #[test]
886 fn test_external_port_defaults() {
887 let config = RtcConfiguration::default();
888 assert_eq!(config.external_port, None);
889 }
890
891 #[test]
892 fn test_external_port_builder() {
893 let config = RtcConfigurationBuilder::new()
894 .external_port(30000)
895 .build();
896 assert_eq!(config.external_port, Some(30000));
897 }
898
899 #[test]
900 fn test_external_port_with_external_ip_builder() {
901 let config = RtcConfigurationBuilder::new()
902 .external_ip("203.0.113.5".to_string())
903 .external_port(30000)
904 .build();
905 assert_eq!(config.external_ip, Some("203.0.113.5".to_string()));
906 assert_eq!(config.external_port, Some(30000));
907 }
908
909 #[test]
910 fn test_upnp_defaults() {
911 let config = RtcConfiguration::default();
912 assert!(!config.enable_upnp, "UPnP should be disabled by default");
913 assert_eq!(config.upnp_lease_duration, 3600);
914 }
915
916 #[test]
917 fn test_upnp_builder_methods() {
918 let config = RtcConfigurationBuilder::new()
919 .enable_upnp(false)
920 .upnp_lease_duration(7200)
921 .build();
922 assert!(!config.enable_upnp);
923 assert_eq!(config.upnp_lease_duration, 7200);
924 }
925
926 #[test]
927 fn test_upnp_optimized_config() {
928 let config = RtcConfigurationBuilder::new()
929 .enable_upnp(true)
930 .upnp_lease_duration(1800)
931 .build();
932
933 assert!(config.enable_upnp);
934 assert_eq!(config.upnp_lease_duration, 1800);
935
936 let defaults = RtcConfiguration::default();
938 assert_eq!(
939 config.ice_connection_timeout,
940 defaults.ice_connection_timeout
941 );
942 }
943}