1#[cfg(test)]
12mod agent_test;
13
14pub mod agent_config;
16mod agent_proto;
17pub mod agent_selector;
19pub mod agent_stats;
21
22use agent_config::*;
23use bytes::BytesMut;
24use crypto::{RTCCrypto, RTCCryptoProvider};
25use log::{debug, error, info, trace, warn};
26use mdns::{Mdns, QueryId};
27use sansio::Protocol;
28use std::collections::{HashMap, VecDeque};
29use std::net::{IpAddr, SocketAddr};
30use std::sync::Arc;
31use std::time::{Duration, Instant};
32use stun::attributes::*;
33use stun::fingerprint::*;
34use stun::integrity::*;
35use stun::message::*;
36use stun::textattrs::*;
37use stun::xoraddr::*;
38
39use crate::candidate::candidate_peer_reflexive::CandidatePeerReflexiveConfig;
40use crate::candidate::{candidate_pair::*, *};
41use crate::mdns::{MulticastDnsMode, create_multicast_dns, generate_multicast_dns_name};
42use crate::network_type::NetworkType;
43use crate::rand::*;
44use crate::state::*;
45use crate::tcp_type::TcpType;
46use crate::url::*;
47use shared::error::*;
48use shared::{TaggedBytesMut, TransportContext, TransportProtocol};
49
50const ZERO_DURATION: Duration = Duration::from_secs(0);
51
52#[derive(Debug, Clone)]
53pub(crate) struct BindingRequest {
54 pub(crate) timestamp: Instant,
55 pub(crate) transaction_id: TransactionId,
56 pub(crate) destination: SocketAddr,
57 pub(crate) is_use_candidate: bool,
58}
59
60#[derive(Default, Clone)]
61pub struct Credentials {
63 pub ufrag: String,
65 pub pwd: String,
67}
68
69#[derive(Default, Clone)]
70pub(crate) struct UfragPwd {
71 pub(crate) local_credentials: Credentials,
72 pub(crate) remote_credentials: Option<Credentials>,
73 pub(crate) pending_local_credentials: Option<Credentials>,
80}
81
82fn assert_inbound_username(m: &Message, expected_username: &str) -> Result<()> {
83 let mut username = Username::new(ATTR_USERNAME, String::new());
84 username.get_from(m)?;
85
86 if username.to_string() != expected_username {
87 return Err(Error::Other(format!(
88 "{:?} expected({}) actual({})",
89 Error::ErrMismatchUsername,
90 expected_username,
91 username,
92 )));
93 }
94
95 Ok(())
96}
97
98fn assert_inbound_message_integrity(
99 m: &mut Message,
100 key: &[u8],
101 crypto: &dyn RTCCrypto,
102) -> Result<()> {
103 MessageIntegrity::check(m, key, crypto)
104}
105
106#[non_exhaustive]
108pub enum Event {
109 ConnectionStateChange(ConnectionState),
111 SelectedCandidatePairChange(Box<Candidate>, Box<Candidate>),
115 RoleChange(bool),
118}
119
120pub struct TaggedEvent {
128 pub now: Instant,
130 pub event: Event,
132}
133
134pub struct Agent {
136 pub(crate) crypto_provider: Arc<dyn RTCCryptoProvider>,
137 pub(crate) tie_breaker: u64,
138 pub(crate) is_controlling: bool,
139 pub(crate) lite: bool,
140
141 pub(crate) start_time: Instant,
142
143 pub(crate) connection_state: ConnectionState,
144 pub(crate) last_connection_state: ConnectionState,
145
146 pub(crate) ufrag_pwd: UfragPwd,
148
149 pub(crate) local_candidates: Vec<Candidate>,
150 pub(crate) remote_candidates: Vec<Candidate>,
151 pub(crate) candidate_pairs: Vec<CandidatePair>,
152 pub(crate) nominated_pair: Option<usize>,
153 pub(crate) selected_pair: Option<usize>,
154
155 pub(crate) pending_binding_requests: Vec<BindingRequest>,
157
158 pub(crate) insecure_skip_verify: bool,
160 pub(crate) max_binding_requests: u16,
161 pub(crate) host_acceptance_min_wait: Duration,
162 pub(crate) srflx_acceptance_min_wait: Duration,
163 pub(crate) prflx_acceptance_min_wait: Duration,
164 pub(crate) relay_acceptance_min_wait: Duration,
165 pub(crate) disconnected_timeout: Duration,
168 pub(crate) failed_timeout: Duration,
171 pub(crate) keepalive_interval: Duration,
174 pub(crate) last_consent_sent: Instant,
176 pub(crate) check_interval: Duration,
178 pub(crate) checking_duration: Instant,
179 pub(crate) last_checking_time: Instant,
180 pub(crate) force_candidate_contact: bool,
186
187 pub(crate) mdns: Option<Mdns>,
188 pub(crate) mdns_queries: HashMap<QueryId, Candidate>,
189
190 pub(crate) mdns_mode: MulticastDnsMode,
191 pub(crate) mdns_local_name: String,
192 pub(crate) mdns_local_ip: Option<IpAddr>,
193
194 pub(crate) candidate_types: Vec<CandidateType>,
195 pub(crate) network_types: Vec<NetworkType>,
196 pub(crate) urls: Vec<Url>,
197
198 pub(crate) write_outs: VecDeque<TaggedBytesMut>,
199 pub(crate) event_outs: VecDeque<TaggedEvent>,
200}
201
202impl Agent {
203 pub fn new(
213 now: Instant,
214 config: Arc<AgentConfig>,
215 crypto_provider: Arc<dyn RTCCryptoProvider>,
216 ) -> Result<Self> {
217 let tie_breaker = generate_tie_breaker(crypto_provider.random())?;
218
219 let mut mdns_local_name = config.multicast_dns_local_name.clone();
220 if mdns_local_name.is_empty() {
221 mdns_local_name = generate_multicast_dns_name();
222 }
223
224 if !mdns_local_name.ends_with(".local") || mdns_local_name.split('.').count() != 2 {
225 return Err(Error::ErrInvalidMulticastDnshostName);
226 }
227
228 let mdns_mode = config.multicast_dns_mode;
229 let mdns = create_multicast_dns(
230 now,
231 mdns_mode,
232 &mdns_local_name,
233 &config.multicast_dns_local_ip,
234 &config.multicast_dns_query_timeout,
235 )
236 .unwrap_or_else(|err| {
237 warn!("Failed to initialize mDNS {mdns_local_name}: {err}");
240 None
241 });
242
243 let candidate_types = if config.candidate_types.is_empty() {
244 default_candidate_types()
245 } else {
246 config.candidate_types.clone()
247 };
248
249 if config.lite && (candidate_types.len() != 1 || candidate_types[0] != CandidateType::Host)
250 {
251 return Err(Error::ErrLiteUsingNonHostCandidates);
252 }
253
254 if !config.urls.is_empty()
255 && !contains_candidate_type(CandidateType::ServerReflexive, &candidate_types)
256 && !contains_candidate_type(CandidateType::Relay, &candidate_types)
257 {
258 return Err(Error::ErrUselessUrlsProvided);
259 }
260
261 let mut agent = Self {
262 crypto_provider,
263 tie_breaker,
264 is_controlling: config.is_controlling,
265 lite: config.lite,
266
267 start_time: now,
268
269 nominated_pair: None,
270 selected_pair: None,
271 candidate_pairs: vec![],
272
273 connection_state: ConnectionState::New,
274
275 insecure_skip_verify: config.insecure_skip_verify,
276
277 max_binding_requests: if let Some(max_binding_requests) = config.max_binding_requests {
281 max_binding_requests
282 } else {
283 DEFAULT_MAX_BINDING_REQUESTS
284 },
285 host_acceptance_min_wait: if let Some(host_acceptance_min_wait) =
286 config.host_acceptance_min_wait
287 {
288 host_acceptance_min_wait
289 } else {
290 DEFAULT_HOST_ACCEPTANCE_MIN_WAIT
291 },
292 srflx_acceptance_min_wait: if let Some(srflx_acceptance_min_wait) =
293 config.srflx_acceptance_min_wait
294 {
295 srflx_acceptance_min_wait
296 } else {
297 DEFAULT_SRFLX_ACCEPTANCE_MIN_WAIT
298 },
299 prflx_acceptance_min_wait: if let Some(prflx_acceptance_min_wait) =
300 config.prflx_acceptance_min_wait
301 {
302 prflx_acceptance_min_wait
303 } else {
304 DEFAULT_PRFLX_ACCEPTANCE_MIN_WAIT
305 },
306 relay_acceptance_min_wait: if let Some(relay_acceptance_min_wait) =
307 config.relay_acceptance_min_wait
308 {
309 relay_acceptance_min_wait
310 } else {
311 DEFAULT_RELAY_ACCEPTANCE_MIN_WAIT
312 },
313
314 disconnected_timeout: if let Some(disconnected_timeout) = config.disconnected_timeout {
317 disconnected_timeout
318 } else {
319 DEFAULT_DISCONNECTED_TIMEOUT
320 },
321
322 failed_timeout: if let Some(failed_timeout) = config.failed_timeout {
325 failed_timeout
326 } else {
327 DEFAULT_FAILED_TIMEOUT
328 },
329
330 keepalive_interval: if let Some(keepalive_interval) = config.keepalive_interval {
333 keepalive_interval
334 } else {
335 DEFAULT_KEEPALIVE_INTERVAL
336 },
337
338 check_interval: if config.check_interval == Duration::from_secs(0) {
340 DEFAULT_CHECK_INTERVAL
341 } else {
342 config.check_interval
343 },
344 last_consent_sent: now,
345 checking_duration: now,
346 last_checking_time: now,
347 force_candidate_contact: false,
348 last_connection_state: ConnectionState::Unspecified,
349
350 mdns,
351 mdns_queries: HashMap::new(),
352
353 mdns_mode,
354 mdns_local_name,
355 mdns_local_ip: config.multicast_dns_local_ip,
356
357 ufrag_pwd: UfragPwd::default(),
358
359 local_candidates: vec![],
360 remote_candidates: vec![],
361
362 pending_binding_requests: vec![],
364
365 candidate_types,
366 network_types: config.network_types.clone(),
367 urls: config.urls.clone(),
368
369 write_outs: VecDeque::new(),
370 event_outs: VecDeque::new(),
371 };
372
373 if let Err(err) = agent.restart(
375 now,
376 config.local_ufrag.clone(),
377 config.local_pwd.clone(),
378 false,
379 ) {
380 let _ = agent.close();
381 return Err(err);
382 }
383
384 Ok(agent)
385 }
386
387 pub fn add_local_candidate(&mut self, mut c: Candidate) -> Result<bool> {
389 if !self.network_types.is_empty() {
391 let candidate_network_type = c.network_type();
392 if !self.network_types.contains(&candidate_network_type) {
393 debug!(
394 "Ignoring local candidate with network type {:?} (not in configured network types: {:?})",
395 candidate_network_type, self.network_types
396 );
397 return Ok(false);
398 }
399 }
400
401 let candidate_type = c.candidate_type();
403 if !self.candidate_types.is_empty() && !self.candidate_types.contains(&candidate_type) {
404 debug!(
405 "Ignoring local candidate with type {:?} (not in configured candidate types: {:?})",
406 candidate_type, self.candidate_types
407 );
408 return Ok(false);
409 }
410
411 if c.candidate_type() == CandidateType::Host
412 && self.mdns_mode == MulticastDnsMode::QueryAndGather
413 && c.network_type == NetworkType::Udp4
414 && self
415 .mdns_local_ip
416 .is_some_and(|local_ip| local_ip == c.addr().ip())
417 {
418 trace!(
421 "mDNS hides local ip {} with local name {}",
422 c.address, self.mdns_local_name
423 );
424 c.address = self.mdns_local_name.clone();
425 }
426
427 for cand in &self.local_candidates {
428 if cand.equal(&c) {
429 return Ok(false);
430 }
431 }
432
433 self.local_candidates.push(c);
434 let local_index = self.local_candidates.len() - 1;
435
436 for remote_index in 0..self.remote_candidates.len() {
437 if self.local_candidates[local_index]
438 .can_pair_with(&self.remote_candidates[remote_index])
439 {
440 self.add_pair(local_index, remote_index);
441 }
442 }
443
444 self.request_connectivity_check();
445
446 Ok(true)
447 }
448
449 pub fn add_remote_candidate(&mut self, c: Candidate) -> Result<bool> {
451 if !self.network_types.is_empty() {
453 let candidate_network_type = c.network_type();
454 if !self.network_types.contains(&candidate_network_type) {
455 debug!(
456 "Ignoring remote candidate with network type {:?} (not in configured network types: {:?})",
457 candidate_network_type, self.network_types
458 );
459 return Ok(false);
460 }
461 }
462
463 if c.tcp_type() == TcpType::Active {
467 debug!(
468 "Ignoring remote candidate with tcptype active: {}",
469 c.address()
470 );
471 return Ok(false);
472 }
473
474 if c.candidate_type() == CandidateType::Host && c.address().ends_with(".local") {
476 if self.mdns_mode == MulticastDnsMode::Disabled {
477 warn!(
478 "remote mDNS candidate added, but mDNS is disabled: ({})",
479 c.address()
480 );
481 return Ok(false);
482 }
483
484 if c.candidate_type() != CandidateType::Host {
485 return Err(Error::ErrAddressParseFailed);
486 }
487
488 if let Some(mdns_conn) = &mut self.mdns {
489 let query_id = mdns_conn.schedule_query(c.address());
490 self.mdns_queries.insert(query_id, c);
491 }
492
493 return Ok(false);
494 }
495
496 self.trigger_request_connectivity_check(vec![c]);
497 Ok(true)
498 }
499
500 fn trigger_request_connectivity_check(&mut self, remote_candidates: Vec<Candidate>) {
501 for c in remote_candidates {
502 if !self.remote_candidates.iter().any(|cand| cand.equal(&c)) {
503 self.remote_candidates.push(c);
504 let remote_index = self.remote_candidates.len() - 1;
505
506 for local_index in 0..self.local_candidates.len() {
507 if self.local_candidates[local_index]
508 .can_pair_with(&self.remote_candidates[remote_index])
509 {
510 self.add_pair(local_index, remote_index);
511 }
512 }
513
514 self.request_connectivity_check();
515 }
516 }
517 }
518
519 pub fn set_remote_credentials(
521 &mut self,
522 remote_ufrag: String,
523 remote_pwd: String,
524 ) -> Result<()> {
525 if remote_ufrag.is_empty() {
526 return Err(Error::ErrRemoteUfragEmpty);
527 } else if remote_pwd.is_empty() {
528 return Err(Error::ErrRemotePwdEmpty);
529 }
530
531 self.ufrag_pwd.remote_credentials = Some(Credentials {
532 ufrag: remote_ufrag,
533 pwd: remote_pwd,
534 });
535
536 Ok(())
537 }
538
539 pub fn get_remote_credentials(&self) -> Option<&Credentials> {
541 self.ufrag_pwd.remote_credentials.as_ref()
542 }
543
544 pub fn get_local_credentials(&self) -> &Credentials {
552 self.ufrag_pwd
553 .pending_local_credentials
554 .as_ref()
555 .unwrap_or(&self.ufrag_pwd.local_credentials)
556 }
557
558 pub fn role(&self) -> bool {
560 self.is_controlling
561 }
562
563 pub fn set_role(&mut self, is_controlling: bool) {
567 self.is_controlling = is_controlling;
568 }
569
570 pub fn state(&self) -> ConnectionState {
572 self.connection_state
573 }
574
575 pub fn is_valid_non_stun_traffic(&mut self, now: Instant, transport: TransportContext) -> bool {
579 self.find_local_candidate(transport.local_addr, transport.transport_protocol)
580 .is_some()
581 && self.validate_non_stun_traffic(now, transport.peer_addr)
582 }
583
584 fn get_timeout_interval(&self) -> Duration {
585 let (check_interval, keepalive_interval, disconnected_timeout, failed_timeout) = (
586 self.check_interval,
587 self.keepalive_interval,
588 self.disconnected_timeout,
589 self.failed_timeout,
590 );
591 let mut interval = DEFAULT_CHECK_INTERVAL;
592
593 let mut update_interval = |x: Duration| {
594 if x != ZERO_DURATION && (interval == ZERO_DURATION || interval > x) {
595 interval = x;
596 }
597 };
598
599 match self.last_connection_state {
600 ConnectionState::New | ConnectionState::Checking => {
601 update_interval(check_interval);
603 }
604 ConnectionState::Connected | ConnectionState::Disconnected => {
605 update_interval(keepalive_interval);
606 }
607 _ => {}
608 };
609 update_interval(disconnected_timeout);
611 update_interval(failed_timeout);
612 interval
613 }
614
615 pub fn get_selected_candidate_pair(&self) -> Option<(&Candidate, &Candidate)> {
617 if let Some(pair_index) = self.get_selected_pair() {
618 let candidate_pair = &self.candidate_pairs[pair_index];
619 Some((
620 &self.local_candidates[candidate_pair.local_index],
621 &self.remote_candidates[candidate_pair.remote_index],
622 ))
623 } else {
624 None
625 }
626 }
627
628 pub fn get_best_available_candidate_pair(&self) -> Option<(&Candidate, &Candidate)> {
630 if let Some(pair_index) = self.get_best_available_pair() {
631 let candidate_pair = &self.candidate_pairs[pair_index];
632 Some((
633 &self.local_candidates[candidate_pair.local_index],
634 &self.remote_candidates[candidate_pair.remote_index],
635 ))
636 } else {
637 None
638 }
639 }
640
641 pub fn start_connectivity_checks(
643 &mut self,
644 now: Instant,
645 is_controlling: bool,
646 remote_ufrag: String,
647 remote_pwd: String,
648 ) -> Result<()> {
649 debug!(
650 "Started agent: isControlling? {}, remoteUfrag: {}, remotePwd: {}",
651 is_controlling, remote_ufrag, remote_pwd
652 );
653 self.set_remote_credentials(remote_ufrag, remote_pwd)?;
654 self.is_controlling = is_controlling;
655 self.start(now);
656
657 self.update_connection_state(Some(now), ConnectionState::Checking);
658 self.request_connectivity_check();
659
660 Ok(())
661 }
662
663 pub fn generate_restart_credentials(
676 &mut self,
677 mut ufrag: String,
678 mut pwd: String,
679 ) -> Result<()> {
680 if ufrag.is_empty() {
681 ufrag = generate_ufrag_with_random(self.crypto_provider.random())?;
682 }
683 if pwd.is_empty() {
684 pwd = generate_pwd_with_random(self.crypto_provider.random())?;
685 }
686
687 if ufrag.len() * 8 < 24 {
688 return Err(Error::ErrLocalUfragInsufficientBits);
689 }
690 if pwd.len() * 8 < 128 {
691 return Err(Error::ErrLocalPwdInsufficientBits);
692 }
693
694 self.ufrag_pwd.pending_local_credentials = Some(Credentials { ufrag, pwd });
695
696 Ok(())
697 }
698
699 pub fn has_pending_restart(&self) -> bool {
701 self.ufrag_pwd.pending_local_credentials.is_some()
702 }
703
704 pub fn apply_restart(&mut self, now: Instant, keep_local_candidates: bool) -> Result<()> {
711 if let Some(credentials) = self.ufrag_pwd.pending_local_credentials.take() {
712 self.ufrag_pwd.local_credentials = credentials;
713 }
714 self.ufrag_pwd.remote_credentials = None;
715
716 self.pending_binding_requests = vec![];
717
718 self.candidate_pairs = vec![];
719
720 self.set_selected_pair(Some(now), None);
721 self.delete_all_candidates(keep_local_candidates);
722 self.start(now);
723
724 if self.connection_state != ConnectionState::New {
727 self.update_connection_state(Some(now), ConnectionState::Checking);
728 }
729
730 Ok(())
731 }
732
733 pub fn restart(
740 &mut self,
741 now: Instant,
742 ufrag: String,
743 pwd: String,
744 keep_local_candidates: bool,
745 ) -> Result<()> {
746 self.generate_restart_credentials(ufrag, pwd)?;
747 self.apply_restart(now, keep_local_candidates)
748 }
749
750 pub fn get_local_candidates(&self) -> &[Candidate] {
752 &self.local_candidates
753 }
754
755 pub fn get_remote_candidates(&self) -> &[Candidate] {
757 &self.remote_candidates
758 }
759
760 fn contact(&mut self, now: Instant) {
761 self.force_candidate_contact = false;
765
766 if self.connection_state == ConnectionState::Failed {
767 self.last_connection_state = self.connection_state;
770 return;
771 }
772 if self.connection_state == ConnectionState::Checking {
773 if self.last_connection_state != self.connection_state {
775 self.checking_duration = now;
776 }
777
778 if self.failed_timeout != ZERO_DURATION
780 && now
781 .checked_duration_since(self.checking_duration)
782 .unwrap_or_else(|| Duration::from_secs(0))
783 > self.disconnected_timeout + self.failed_timeout
784 {
785 self.update_connection_state(Some(now), ConnectionState::Failed);
786 self.last_connection_state = self.connection_state;
787 return;
788 }
789 }
790
791 self.contact_candidates(now);
792
793 self.last_connection_state = self.connection_state;
794 self.last_checking_time = now;
795 }
796
797 pub(crate) fn update_connection_state(
798 &mut self,
799 now: Option<Instant>,
800 new_state: ConnectionState,
801 ) {
802 if self.connection_state != new_state {
803 if new_state == ConnectionState::Failed {
805 self.set_selected_pair(now, None);
806 self.delete_all_candidates(false);
807 }
808
809 info!(
810 "[{}]: Setting new connection state: {}",
811 self.get_name(),
812 new_state
813 );
814 self.connection_state = new_state;
815 if let Some(now) = now {
816 self.event_outs.push_back(TaggedEvent {
817 now,
818 event: Event::ConnectionStateChange(new_state),
819 });
820 }
821 }
822 }
823
824 pub(crate) fn set_selected_pair(&mut self, now: Option<Instant>, selected_pair: Option<usize>) {
825 if let Some(pair_index) = selected_pair {
826 trace!(
827 "[{}]: Set selected candidate pair: {:?}",
828 self.get_name(),
829 self.candidate_pairs[pair_index]
830 );
831
832 self.candidate_pairs[pair_index].nominated = true;
833 self.selected_pair = Some(pair_index);
834
835 self.update_connection_state(now, ConnectionState::Connected);
836
837 let candidate_pair = &self.candidate_pairs[pair_index];
839 if let Some(now) = now {
840 self.event_outs.push_back(TaggedEvent {
841 now,
842 event: Event::SelectedCandidatePairChange(
843 Box::new(self.local_candidates[candidate_pair.local_index].clone()),
844 Box::new(self.remote_candidates[candidate_pair.remote_index].clone()),
845 ),
846 });
847 }
848 } else {
849 self.selected_pair = None;
850 }
851 }
852
853 pub(crate) fn ping_all_candidates(&mut self, now: Instant) {
854 let mut pairs: Vec<(usize, usize)> = vec![];
855
856 let name = self.get_name().to_string();
857 if self.candidate_pairs.is_empty() {
858 warn!(
859 "[{}]: pingAllCandidates called with no candidate pairs. Connection is not possible yet.",
860 name,
861 );
862 }
863 for p in &mut self.candidate_pairs {
864 if p.state == CandidatePairState::Waiting {
865 p.state = CandidatePairState::InProgress;
866 } else if p.state != CandidatePairState::InProgress {
867 continue;
868 }
869
870 if p.binding_request_count > self.max_binding_requests {
871 trace!(
872 "[{}]: max requests reached for pair {} (local_addr {} <-> remote_addr {}), marking it as failed",
873 name,
874 *p,
875 self.local_candidates[p.local_index].addr(),
876 self.remote_candidates[p.remote_index].addr()
877 );
878 p.state = CandidatePairState::Failed;
879 } else {
880 p.binding_request_count += 1;
881 let local = p.local_index;
882 let remote = p.remote_index;
883 pairs.push((local, remote));
884 }
885 }
886
887 if !pairs.is_empty() {
888 trace!(
889 "[{}]: pinging all {} candidates",
890 self.get_name(),
891 pairs.len()
892 );
893 }
894
895 for (local, remote) in pairs {
896 self.ping_candidate(now, local, remote);
897 }
898 }
899
900 pub(crate) fn add_pair(&mut self, local_index: usize, remote_index: usize) {
901 let p = CandidatePair::new(
902 local_index,
903 remote_index,
904 self.local_candidates[local_index].priority(),
905 self.remote_candidates[remote_index].priority(),
906 self.is_controlling,
907 );
908 self.candidate_pairs.push(p);
909 }
910
911 pub(crate) fn find_pair(&self, local_index: usize, remote_index: usize) -> Option<usize> {
912 for (index, p) in self.candidate_pairs.iter().enumerate() {
913 if p.local_index == local_index && p.remote_index == remote_index {
914 return Some(index);
915 }
916 }
917 None
918 }
919
920 pub(crate) fn validate_selected_pair(&mut self, now: Instant) -> bool {
927 let (valid, disconnected_time) = {
928 self.selected_pair.as_ref().map_or_else(
929 || (false, Duration::from_secs(0)),
930 |&pair_index| {
931 let remote_index = self.candidate_pairs[pair_index].remote_index;
932
933 let last_received = self.remote_candidates[remote_index]
934 .last_received()
935 .unwrap_or(self.start_time);
936 let disconnected_time = now.saturating_duration_since(last_received);
937 (true, disconnected_time)
938 },
939 )
940 };
941
942 if valid {
943 let mut total_time_to_failure = self.failed_timeout;
945 if total_time_to_failure != Duration::from_secs(0) {
946 total_time_to_failure += self.disconnected_timeout;
947 }
948
949 if total_time_to_failure != Duration::from_secs(0)
950 && disconnected_time > total_time_to_failure
951 {
952 self.update_connection_state(Some(now), ConnectionState::Failed);
953 } else if self.disconnected_timeout != Duration::from_secs(0)
954 && disconnected_time > self.disconnected_timeout
955 {
956 self.update_connection_state(Some(now), ConnectionState::Disconnected);
957 } else {
958 self.update_connection_state(Some(now), ConnectionState::Connected);
959 }
960 }
961
962 valid
963 }
964
965 pub(crate) fn check_keepalive(&mut self, now: Instant) {
968 let (local_index, remote_index, pair_index) = {
969 self.selected_pair
970 .as_ref()
971 .map_or((None, None, None), |&pair_index| {
972 let p = &self.candidate_pairs[pair_index];
973 (Some(p.local_index), Some(p.remote_index), Some(pair_index))
974 })
975 };
976
977 if let (Some(local_index), Some(remote_index), Some(pair_index)) =
978 (local_index, remote_index, pair_index)
979 && self.keepalive_interval != Duration::from_secs(0)
980 && now.saturating_duration_since(self.last_consent_sent) >= self.keepalive_interval
981 {
982 self.last_consent_sent = now;
983 self.candidate_pairs[pair_index].on_consent_request_sent();
984 self.ping_candidate(now, local_index, remote_index);
985 }
986 }
987
988 fn request_connectivity_check(&mut self) {
989 self.force_candidate_contact = true;
995 }
996
997 pub(crate) fn delete_all_candidates(&mut self, keep_local_candidates: bool) {
1002 if !keep_local_candidates {
1003 self.local_candidates.clear();
1004 }
1005 self.remote_candidates.clear();
1006
1007 self.candidate_pairs.clear();
1013 self.selected_pair = None;
1014 self.nominated_pair = None;
1015 }
1016
1017 pub(crate) fn find_remote_candidate(&self, addr: SocketAddr) -> Option<usize> {
1018 for (index, c) in self.remote_candidates.iter().enumerate() {
1019 if c.addr() == addr {
1020 return Some(index);
1021 }
1022 }
1023 None
1024 }
1025
1026 pub(crate) fn find_local_candidate(
1027 &self,
1028 addr: SocketAddr,
1029 transport_protocol: TransportProtocol,
1030 ) -> Option<usize> {
1031 for (index, c) in self.local_candidates.iter().enumerate() {
1032 if c.network_type().to_protocol() != transport_protocol {
1033 continue;
1034 }
1035
1036 if c.tcp_type() == TcpType::Active && transport_protocol == TransportProtocol::TCP {
1040 if c.addr().ip() == addr.ip() {
1041 return Some(index);
1042 }
1043 } else if c.addr() == addr {
1044 return Some(index);
1045 } else if let Some(related_address) = c.related_address()
1046 && related_address.address == addr.ip().to_string()
1047 && related_address.port == addr.port()
1048 {
1049 return Some(index);
1050 }
1051 }
1052 None
1053 }
1054
1055 pub(crate) fn send_binding_request(
1056 &mut self,
1057 now: Instant,
1058 m: &Message,
1059 local_index: usize,
1060 remote_index: usize,
1061 ) {
1062 trace!(
1063 "[{}]: ping STUN from {} to {}",
1064 self.get_name(),
1065 self.local_candidates[local_index],
1066 self.remote_candidates[remote_index],
1067 );
1068
1069 self.invalidate_pending_binding_requests(now);
1070
1071 self.pending_binding_requests.push(BindingRequest {
1072 timestamp: now,
1073 transaction_id: m.transaction_id,
1074 destination: self.remote_candidates[remote_index].addr(),
1075 is_use_candidate: m.contains(ATTR_USE_CANDIDATE),
1076 });
1077
1078 if let Some(pair_index) = self.find_pair(local_index, remote_index) {
1080 self.candidate_pairs[pair_index].on_request_sent();
1081 }
1082
1083 self.send_stun(now, m, local_index, remote_index);
1084 }
1085
1086 pub(crate) fn send_binding_success(
1087 &mut self,
1088 now: Instant,
1089 m: &Message,
1090 local_index: usize,
1091 remote_index: usize,
1092 ) {
1093 let addr = self.remote_candidates[remote_index].addr();
1094 let (ip, port) = (addr.ip(), addr.port());
1095 let local_pwd = self.ufrag_pwd.local_credentials.pwd.clone();
1096
1097 let (out, result) = {
1098 let mut out = Message::new();
1099 let result = out.build(&[
1100 Box::new(m.clone()),
1101 Box::new(BINDING_SUCCESS),
1102 Box::new(XorMappedAddress { ip, port }),
1103 Box::new(MessageIntegrity::new_short_term_integrity_with_provider(
1104 local_pwd,
1105 self.crypto_provider.crypto(),
1106 )),
1107 Box::new(FINGERPRINT),
1108 ]);
1109 (out, result)
1110 };
1111
1112 if let Err(err) = result {
1113 warn!(
1114 "[{}]: Failed to handle inbound ICE from: {} to: {} error: {}",
1115 self.get_name(),
1116 self.local_candidates[local_index],
1117 self.remote_candidates[remote_index],
1118 err
1119 );
1120 } else {
1121 if let Some(pair_index) = self.find_pair(local_index, remote_index) {
1123 self.candidate_pairs[pair_index].on_response_sent();
1124 }
1125 self.send_stun(now, &out, local_index, remote_index);
1126 }
1127 }
1128
1129 pub(crate) fn send_role_conflict_error(
1132 &mut self,
1133 now: Instant,
1134 m: &Message,
1135 local_index: usize,
1136 remote_index: usize,
1137 ) {
1138 use stun::error_code::*;
1139
1140 let local_pwd = self.ufrag_pwd.local_credentials.pwd.clone();
1141
1142 let (out, result) = {
1143 let mut out = Message::new();
1144 let result = out.build(&[
1145 Box::new(m.clone()),
1146 Box::new(stun::message::BINDING_ERROR),
1147 Box::new(CODE_ROLE_CONFLICT),
1148 Box::new(MessageIntegrity::new_short_term_integrity_with_provider(
1149 local_pwd,
1150 self.crypto_provider.crypto(),
1151 )),
1152 Box::new(FINGERPRINT),
1153 ]);
1154 (out, result)
1155 };
1156
1157 if let Err(err) = result {
1158 warn!(
1159 "[{}]: Failed to send role conflict error from: {} to: {} error: {}",
1160 self.get_name(),
1161 self.local_candidates[local_index],
1162 self.remote_candidates[remote_index],
1163 err
1164 );
1165 } else {
1166 debug!(
1167 "[{}]: Sent 487 Role Conflict error from {} to {}",
1168 self.get_name(),
1169 self.local_candidates[local_index],
1170 self.remote_candidates[remote_index]
1171 );
1172 self.send_stun(now, &out, local_index, remote_index);
1173 }
1174 }
1175
1176 pub(crate) fn switch_role(&mut self, now: Instant) {
1179 self.is_controlling = !self.is_controlling;
1180
1181 for pair in &mut self.candidate_pairs {
1184 pair.ice_role_controlling = self.is_controlling;
1185 }
1186
1187 self.nominated_pair = None;
1189
1190 info!(
1191 "[{}]: Role switched, recomputed {} candidate pair priorities",
1192 self.get_name(),
1193 self.candidate_pairs.len()
1194 );
1195
1196 self.event_outs.push_back(TaggedEvent {
1197 now,
1198 event: Event::RoleChange(self.is_controlling),
1199 });
1200 }
1201
1202 pub(crate) fn invalidate_pending_binding_requests(&mut self, filter_time: Instant) {
1207 let pending_binding_requests = &mut self.pending_binding_requests;
1208 let initial_size = pending_binding_requests.len();
1209
1210 let mut temp = vec![];
1211 for binding_request in pending_binding_requests.drain(..) {
1212 if filter_time
1213 .checked_duration_since(binding_request.timestamp)
1214 .map(|duration| duration < MAX_BINDING_REQUEST_TIMEOUT)
1215 .unwrap_or(true)
1216 {
1217 temp.push(binding_request);
1218 }
1219 }
1220
1221 *pending_binding_requests = temp;
1222 let bind_requests_remaining = pending_binding_requests.len();
1223 let bind_requests_removed = initial_size - bind_requests_remaining;
1224 if bind_requests_removed > 0 {
1225 trace!(
1226 "[{}]: Discarded {} binding requests because they expired, still {} remaining",
1227 self.get_name(),
1228 bind_requests_removed,
1229 bind_requests_remaining,
1230 );
1231 }
1232 }
1233
1234 pub(crate) fn handle_inbound_binding_success(
1237 &mut self,
1238 now: Instant,
1239 id: TransactionId,
1240 ) -> Option<BindingRequest> {
1241 self.invalidate_pending_binding_requests(now);
1242
1243 let pending_binding_requests = &mut self.pending_binding_requests;
1244 for i in 0..pending_binding_requests.len() {
1245 if pending_binding_requests[i].transaction_id == id {
1246 let valid_binding_request = pending_binding_requests.remove(i);
1247 return Some(valid_binding_request);
1248 }
1249 }
1250 None
1251 }
1252
1253 pub(crate) fn handle_inbound(
1255 &mut self,
1256 now: Instant,
1257 m: &mut Message,
1258 local_index: usize,
1259 remote_addr: SocketAddr,
1260 ) -> Result<()> {
1261 if m.typ.method != METHOD_BINDING
1262 || !(m.typ.class == CLASS_SUCCESS_RESPONSE
1263 || m.typ.class == CLASS_REQUEST
1264 || m.typ.class == CLASS_INDICATION)
1265 {
1266 trace!(
1267 "[{}]: unhandled STUN from {} to {} class({}) method({})",
1268 self.get_name(),
1269 remote_addr,
1270 self.local_candidates[local_index],
1271 m.typ.class,
1272 m.typ.method
1273 );
1274 return Err(Error::ErrUnhandledStunpacket);
1275 }
1276
1277 if self.is_controlling {
1279 if m.contains(ATTR_ICE_CONTROLLING) {
1280 let mut remote_controlling = crate::attributes::control::AttrControlling::default();
1282 if let Err(err) = remote_controlling.get_from(m) {
1283 warn!(
1284 "[{}]: Failed to get remote ICE-CONTROLLING attribute: {}",
1285 self.get_name(),
1286 err
1287 );
1288 return Err(err);
1289 }
1290
1291 debug!(
1292 "[{}]: Role conflict detected (both controlling), local tiebreaker: {}, remote tiebreaker: {}",
1293 self.get_name(),
1294 self.tie_breaker,
1295 remote_controlling.0
1296 );
1297
1298 if m.typ.class == CLASS_REQUEST {
1300 if let Some(remote_index) = self.find_remote_candidate(remote_addr) {
1302 self.send_role_conflict_error(now, m, local_index, remote_index);
1303 }
1304
1305 if self.tie_breaker < remote_controlling.0 {
1307 info!(
1308 "[{}]: Switching from controlling to controlled due to role conflict (smaller tiebreaker)",
1309 self.get_name()
1310 );
1311 self.switch_role(now);
1312 }
1313 }
1314 } else if m.contains(ATTR_USE_CANDIDATE) {
1316 debug!(
1317 "[{}]: useCandidate && a.isControlling == true",
1318 self.get_name(),
1319 );
1320 return Err(Error::ErrUnexpectedStunrequestMessage);
1321 }
1322 } else if m.contains(ATTR_ICE_CONTROLLED) {
1323 let mut remote_controlled = crate::attributes::control::AttrControlled::default();
1325 if let Err(err) = remote_controlled.get_from(m) {
1326 warn!(
1327 "[{}]: Failed to get remote ICE-CONTROLLED attribute: {}",
1328 self.get_name(),
1329 err
1330 );
1331 return Err(err);
1332 }
1333
1334 debug!(
1335 "[{}]: Role conflict detected (both controlled), local tiebreaker: {}, remote tiebreaker: {}",
1336 self.get_name(),
1337 self.tie_breaker,
1338 remote_controlled.0
1339 );
1340
1341 if m.typ.class == CLASS_REQUEST {
1343 if let Some(remote_index) = self.find_remote_candidate(remote_addr) {
1345 self.send_role_conflict_error(now, m, local_index, remote_index);
1346 }
1347
1348 if self.tie_breaker > remote_controlled.0 {
1350 info!(
1351 "[{}]: Switching from controlled to controlling due to role conflict (larger tiebreaker)",
1352 self.get_name()
1353 );
1354 self.switch_role(now);
1355 }
1356 }
1357 }
1359
1360 let Some(remote_credentials) = &self.ufrag_pwd.remote_credentials else {
1361 debug!(
1362 "[{}]: ufrag_pwd.remote_credentials.is_none",
1363 self.get_name(),
1364 );
1365 return Err(Error::ErrPasswordEmpty);
1366 };
1367
1368 let mut remote_candidate_index = self.find_remote_candidate(remote_addr);
1369 if m.typ.class == CLASS_SUCCESS_RESPONSE {
1370 if let Err(err) = assert_inbound_message_integrity(
1371 m,
1372 remote_credentials.pwd.as_bytes(),
1373 self.crypto_provider.crypto(),
1374 ) {
1375 warn!(
1376 "[{}]: discard message from ({}), {}",
1377 self.get_name(),
1378 remote_addr,
1379 err
1380 );
1381 return Err(err);
1382 }
1383
1384 if let Some(remote_index) = &remote_candidate_index {
1385 self.handle_success_response(now, m, local_index, *remote_index, remote_addr);
1386 } else {
1387 warn!(
1388 "[{}]: discard success message from ({}), no such remote",
1389 self.get_name(),
1390 remote_addr
1391 );
1392 return Err(Error::ErrUnhandledStunpacket);
1393 }
1394 } else if m.typ.class == CLASS_REQUEST {
1395 {
1396 let username = self.ufrag_pwd.local_credentials.ufrag.clone()
1397 + ":"
1398 + remote_credentials.ufrag.as_str();
1399 if let Err(err) = assert_inbound_username(m, &username) {
1400 warn!(
1401 "[{}]: discard message from ({}), {}",
1402 self.get_name(),
1403 remote_addr,
1404 err
1405 );
1406 return Err(err);
1407 } else if let Err(err) = assert_inbound_message_integrity(
1408 m,
1409 self.ufrag_pwd.local_credentials.pwd.as_bytes(),
1410 self.crypto_provider.crypto(),
1411 ) {
1412 warn!(
1413 "[{}]: discard message from ({}), {}",
1414 self.get_name(),
1415 remote_addr,
1416 err
1417 );
1418 return Err(err);
1419 }
1420 }
1421
1422 if remote_candidate_index.is_none() {
1423 let network_type = self.local_candidates[local_index].network_type();
1425 let (ip, port) = (remote_addr.ip(), remote_addr.port());
1426
1427 let prflx_candidate_config = CandidatePeerReflexiveConfig {
1428 base_config: CandidateConfig {
1429 network: network_type.to_string(),
1430 address: ip.to_string(),
1431 port,
1432 component: self.local_candidates[local_index].component(),
1433 ..CandidateConfig::default()
1434 },
1435 rel_addr: "".to_owned(),
1436 rel_port: 0,
1437 };
1438
1439 match prflx_candidate_config.new_candidate_peer_reflexive() {
1440 Ok(prflx_candidate) => {
1441 if let Ok(added) = self.add_remote_candidate(prflx_candidate)
1442 && added
1443 {
1444 remote_candidate_index = self.find_remote_candidate(remote_addr);
1449 }
1450 }
1451 Err(err) => {
1452 error!(
1453 "[{}]: Failed to create new remote prflx candidate ({})",
1454 self.get_name(),
1455 err
1456 );
1457 return Err(err);
1458 }
1459 };
1460
1461 debug!(
1462 "[{}]: adding a new peer-reflexive candidate: {} ",
1463 self.get_name(),
1464 remote_addr
1465 );
1466 }
1467
1468 trace!(
1469 "[{}]: inbound STUN (Request) from {} to {}",
1470 self.get_name(),
1471 remote_addr,
1472 self.local_candidates[local_index]
1473 );
1474
1475 if let Some(remote_index) = &remote_candidate_index {
1476 self.handle_binding_request(now, m, local_index, *remote_index);
1477 }
1478 }
1479
1480 if let Some(remote_index) = remote_candidate_index {
1481 self.remote_candidates[remote_index].seen(now, false);
1482 }
1483
1484 Ok(())
1485 }
1486
1487 pub(crate) fn validate_non_stun_traffic(
1490 &mut self,
1491 now: Instant,
1492 remote_addr: SocketAddr,
1493 ) -> bool {
1494 self.find_remote_candidate(remote_addr)
1495 .is_some_and(|remote_index| {
1496 self.remote_candidates[remote_index].seen(now, false);
1497 true
1498 })
1499 }
1500
1501 pub(crate) fn send_stun(
1502 &mut self,
1503 now: Instant,
1504 msg: &Message,
1505 local_index: usize,
1506 remote_index: usize,
1507 ) {
1508 let peer_addr = self.remote_candidates[remote_index].addr();
1509 let local_addr = self.local_candidates[local_index].base_addr();
1513 let transport_protocol = if self.local_candidates[local_index].network_type().is_tcp() {
1514 TransportProtocol::TCP
1515 } else {
1516 TransportProtocol::UDP
1517 };
1518
1519 self.write_outs.push_back(TaggedBytesMut {
1520 now,
1521 transport: TransportContext {
1522 local_addr,
1523 peer_addr,
1524 ecn: None,
1525 transport_protocol,
1526 },
1527 message: BytesMut::from(&msg.raw[..]),
1528 });
1529
1530 self.local_candidates[local_index].seen(now, true);
1531 }
1532
1533 fn handle_inbound_candidate_msg(
1534 &mut self,
1535 local_index: usize,
1536 msg: TaggedBytesMut,
1537 ) -> Result<()> {
1538 if is_stun_message(&msg.message) {
1539 let mut m = Message {
1540 raw: msg.message.to_vec(),
1541 ..Message::default()
1542 };
1543
1544 if let Err(err) = m.decode() {
1545 warn!(
1546 "[{}]: Failed to handle decode ICE from {} to {}: {}",
1547 self.get_name(),
1548 msg.transport.local_addr,
1549 msg.transport.peer_addr,
1550 err
1551 );
1552 Err(err)
1553 } else {
1554 self.handle_inbound(msg.now, &mut m, local_index, msg.transport.peer_addr)
1555 }
1556 } else {
1557 if !self.validate_non_stun_traffic(msg.now, msg.transport.peer_addr) {
1558 warn!(
1559 "[{}]: Discarded message, not a valid remote candidate from {}",
1560 self.get_name(),
1561 msg.transport.peer_addr,
1562 );
1563 } else {
1564 warn!(
1565 "[{}]: non-STUN traffic message from a valid remote candidate from {}",
1566 self.get_name(),
1567 msg.transport.peer_addr
1568 );
1569 }
1570 Err(Error::ErrNonStunmessage)
1571 }
1572 }
1573
1574 pub(crate) fn get_name(&self) -> &str {
1575 if self.is_controlling {
1576 "controlling"
1577 } else {
1578 "controlled"
1579 }
1580 }
1581
1582 pub(crate) fn get_selected_pair(&self) -> Option<usize> {
1583 self.selected_pair
1584 }
1585
1586 pub(crate) fn get_best_available_pair(&self) -> Option<usize> {
1587 let mut best_pair_index: Option<usize> = None;
1588
1589 for (index, p) in self.candidate_pairs.iter().enumerate() {
1590 if p.state == CandidatePairState::Failed {
1591 continue;
1592 }
1593
1594 if let Some(pair_index) = &mut best_pair_index {
1595 let b = &self.candidate_pairs[*pair_index];
1596 if b.priority() < p.priority() {
1597 *pair_index = index;
1598 }
1599 } else {
1600 best_pair_index = Some(index);
1601 }
1602 }
1603
1604 best_pair_index
1605 }
1606
1607 pub(crate) fn get_best_valid_candidate_pair(&self) -> Option<usize> {
1608 let mut best_pair_index: Option<usize> = None;
1609
1610 for (index, p) in self.candidate_pairs.iter().enumerate() {
1611 if p.state != CandidatePairState::Succeeded {
1612 continue;
1613 }
1614
1615 if let Some(pair_index) = &mut best_pair_index {
1616 let b = &self.candidate_pairs[*pair_index];
1617 if b.priority() < p.priority() {
1618 *pair_index = index;
1619 }
1620 } else {
1621 best_pair_index = Some(index);
1622 }
1623 }
1624
1625 best_pair_index
1626 }
1627}