1#[cfg(test)]
2mod agent_test;
3
4pub mod agent_config;
5mod agent_proto;
6pub mod agent_selector;
7pub mod agent_stats;
8
9use agent_config::*;
10use bytes::BytesMut;
11use log::{debug, error, info, trace, warn};
12use mdns::{Mdns, QueryId};
13use sansio::Protocol;
14use std::collections::{HashMap, VecDeque};
15use std::net::{IpAddr, Ipv4Addr, SocketAddr};
16use std::sync::Arc;
17use std::time::{Duration, Instant};
18use stun::attributes::*;
19use stun::fingerprint::*;
20use stun::integrity::*;
21use stun::message::*;
22use stun::textattrs::*;
23use stun::xoraddr::*;
24
25use crate::candidate::candidate_peer_reflexive::CandidatePeerReflexiveConfig;
26use crate::candidate::{candidate_pair::*, *};
27use crate::mdns::{MulticastDnsMode, create_multicast_dns, generate_multicast_dns_name};
28use crate::network_type::NetworkType;
29use crate::rand::*;
30use crate::state::*;
31use crate::tcp_type::TcpType;
32use crate::url::*;
33use shared::error::*;
34use shared::{TaggedBytesMut, TransportContext, TransportProtocol};
35
36const ZERO_DURATION: Duration = Duration::from_secs(0);
37
38#[derive(Debug, Clone)]
39pub(crate) struct BindingRequest {
40 pub(crate) timestamp: Instant,
41 pub(crate) transaction_id: TransactionId,
42 pub(crate) destination: SocketAddr,
43 pub(crate) is_use_candidate: bool,
44}
45
46impl Default for BindingRequest {
47 fn default() -> Self {
48 Self {
49 timestamp: Instant::now(),
50 transaction_id: TransactionId::default(),
51 destination: SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 0),
52 is_use_candidate: false,
53 }
54 }
55}
56
57#[derive(Default, Clone)]
58pub struct Credentials {
59 pub ufrag: String,
60 pub pwd: String,
61}
62
63#[derive(Default, Clone)]
64pub(crate) struct UfragPwd {
65 pub(crate) local_credentials: Credentials,
66 pub(crate) remote_credentials: Option<Credentials>,
67}
68
69fn assert_inbound_username(m: &Message, expected_username: &str) -> Result<()> {
70 let mut username = Username::new(ATTR_USERNAME, String::new());
71 username.get_from(m)?;
72
73 if username.to_string() != expected_username {
74 return Err(Error::Other(format!(
75 "{:?} expected({}) actual({})",
76 Error::ErrMismatchUsername,
77 expected_username,
78 username,
79 )));
80 }
81
82 Ok(())
83}
84
85fn assert_inbound_message_integrity(m: &mut Message, key: &[u8]) -> Result<()> {
86 let message_integrity_attr = MessageIntegrity(key.to_vec());
87 message_integrity_attr.check(m)
88}
89
90pub enum Event {
91 ConnectionStateChange(ConnectionState),
92 SelectedCandidatePairChange(Box<Candidate>, Box<Candidate>),
93 RoleChange(bool),
96}
97
98pub struct Agent {
100 pub(crate) tie_breaker: u64,
101 pub(crate) is_controlling: bool,
102 pub(crate) lite: bool,
103
104 pub(crate) start_time: Instant,
105
106 pub(crate) connection_state: ConnectionState,
107 pub(crate) last_connection_state: ConnectionState,
108
109 pub(crate) ufrag_pwd: UfragPwd,
111
112 pub(crate) local_candidates: Vec<Candidate>,
113 pub(crate) remote_candidates: Vec<Candidate>,
114 pub(crate) candidate_pairs: Vec<CandidatePair>,
115 pub(crate) nominated_pair: Option<usize>,
116 pub(crate) selected_pair: Option<usize>,
117
118 pub(crate) pending_binding_requests: Vec<BindingRequest>,
120
121 pub(crate) insecure_skip_verify: bool,
123 pub(crate) max_binding_requests: u16,
124 pub(crate) host_acceptance_min_wait: Duration,
125 pub(crate) srflx_acceptance_min_wait: Duration,
126 pub(crate) prflx_acceptance_min_wait: Duration,
127 pub(crate) relay_acceptance_min_wait: Duration,
128 pub(crate) disconnected_timeout: Duration,
131 pub(crate) failed_timeout: Duration,
134 pub(crate) keepalive_interval: Duration,
137 pub(crate) last_consent_sent: Instant,
139 pub(crate) check_interval: Duration,
141 pub(crate) checking_duration: Instant,
142 pub(crate) last_checking_time: Instant,
143
144 pub(crate) mdns: Option<Mdns>,
145 pub(crate) mdns_queries: HashMap<QueryId, Candidate>,
146
147 pub(crate) mdns_mode: MulticastDnsMode,
148 pub(crate) mdns_local_name: String,
149 pub(crate) mdns_local_ip: Option<IpAddr>,
150
151 pub(crate) candidate_types: Vec<CandidateType>,
152 pub(crate) network_types: Vec<NetworkType>,
153 pub(crate) urls: Vec<Url>,
154
155 pub(crate) write_outs: VecDeque<TaggedBytesMut>,
156 pub(crate) event_outs: VecDeque<Event>,
157}
158
159impl Default for Agent {
160 fn default() -> Self {
161 Self {
162 tie_breaker: 0,
163 is_controlling: false,
164 lite: false,
165 start_time: Instant::now(),
166 connection_state: Default::default(),
167 last_connection_state: Default::default(),
168 ufrag_pwd: Default::default(),
169 local_candidates: vec![],
170 remote_candidates: vec![],
171 candidate_pairs: vec![],
172 nominated_pair: None,
173 selected_pair: None,
174 pending_binding_requests: vec![],
175 insecure_skip_verify: false,
176 max_binding_requests: 0,
177 host_acceptance_min_wait: Default::default(),
178 srflx_acceptance_min_wait: Default::default(),
179 prflx_acceptance_min_wait: Default::default(),
180 relay_acceptance_min_wait: Default::default(),
181 disconnected_timeout: Default::default(),
182 failed_timeout: Default::default(),
183 keepalive_interval: Default::default(),
184 last_consent_sent: Instant::now(),
185 check_interval: Default::default(),
186 checking_duration: Instant::now(),
187 last_checking_time: Instant::now(),
188 mdns_mode: MulticastDnsMode::Disabled,
189 mdns_local_name: "".to_owned(),
190 mdns_local_ip: None,
191 mdns_queries: HashMap::new(),
192 mdns: None,
193 candidate_types: vec![],
194 network_types: vec![],
195 urls: vec![],
196 write_outs: Default::default(),
197 event_outs: Default::default(),
198 }
199 }
200}
201
202impl Agent {
203 pub fn new(config: Arc<AgentConfig>) -> Result<Self> {
205 let mut mdns_local_name = config.multicast_dns_local_name.clone();
206 if mdns_local_name.is_empty() {
207 mdns_local_name = generate_multicast_dns_name();
208 }
209
210 if !mdns_local_name.ends_with(".local") || mdns_local_name.split('.').count() != 2 {
211 return Err(Error::ErrInvalidMulticastDnshostName);
212 }
213
214 let mdns_mode = config.multicast_dns_mode;
215 let mdns = create_multicast_dns(
216 mdns_mode,
217 &mdns_local_name,
218 &config.multicast_dns_local_ip,
219 &config.multicast_dns_query_timeout,
220 )
221 .unwrap_or_else(|err| {
222 warn!("Failed to initialize mDNS {mdns_local_name}: {err}");
225 None
226 });
227
228 let candidate_types = if config.candidate_types.is_empty() {
229 default_candidate_types()
230 } else {
231 config.candidate_types.clone()
232 };
233
234 if config.lite && (candidate_types.len() != 1 || candidate_types[0] != CandidateType::Host)
235 {
236 return Err(Error::ErrLiteUsingNonHostCandidates);
237 }
238
239 if !config.urls.is_empty()
240 && !contains_candidate_type(CandidateType::ServerReflexive, &candidate_types)
241 && !contains_candidate_type(CandidateType::Relay, &candidate_types)
242 {
243 return Err(Error::ErrUselessUrlsProvided);
244 }
245
246 let mut agent = Self {
247 tie_breaker: rand::random::<u64>(),
248 is_controlling: config.is_controlling,
249 lite: config.lite,
250
251 start_time: Instant::now(),
252
253 nominated_pair: None,
254 selected_pair: None,
255 candidate_pairs: vec![],
256
257 connection_state: ConnectionState::New,
258
259 insecure_skip_verify: config.insecure_skip_verify,
260
261 max_binding_requests: if let Some(max_binding_requests) = config.max_binding_requests {
265 max_binding_requests
266 } else {
267 DEFAULT_MAX_BINDING_REQUESTS
268 },
269 host_acceptance_min_wait: if let Some(host_acceptance_min_wait) =
270 config.host_acceptance_min_wait
271 {
272 host_acceptance_min_wait
273 } else {
274 DEFAULT_HOST_ACCEPTANCE_MIN_WAIT
275 },
276 srflx_acceptance_min_wait: if let Some(srflx_acceptance_min_wait) =
277 config.srflx_acceptance_min_wait
278 {
279 srflx_acceptance_min_wait
280 } else {
281 DEFAULT_SRFLX_ACCEPTANCE_MIN_WAIT
282 },
283 prflx_acceptance_min_wait: if let Some(prflx_acceptance_min_wait) =
284 config.prflx_acceptance_min_wait
285 {
286 prflx_acceptance_min_wait
287 } else {
288 DEFAULT_PRFLX_ACCEPTANCE_MIN_WAIT
289 },
290 relay_acceptance_min_wait: if let Some(relay_acceptance_min_wait) =
291 config.relay_acceptance_min_wait
292 {
293 relay_acceptance_min_wait
294 } else {
295 DEFAULT_RELAY_ACCEPTANCE_MIN_WAIT
296 },
297
298 disconnected_timeout: if let Some(disconnected_timeout) = config.disconnected_timeout {
301 disconnected_timeout
302 } else {
303 DEFAULT_DISCONNECTED_TIMEOUT
304 },
305
306 failed_timeout: if let Some(failed_timeout) = config.failed_timeout {
309 failed_timeout
310 } else {
311 DEFAULT_FAILED_TIMEOUT
312 },
313
314 keepalive_interval: if let Some(keepalive_interval) = config.keepalive_interval {
317 keepalive_interval
318 } else {
319 DEFAULT_KEEPALIVE_INTERVAL
320 },
321
322 check_interval: if config.check_interval == Duration::from_secs(0) {
324 DEFAULT_CHECK_INTERVAL
325 } else {
326 config.check_interval
327 },
328 last_consent_sent: Instant::now(),
329 checking_duration: Instant::now(),
330 last_checking_time: Instant::now(),
331 last_connection_state: ConnectionState::Unspecified,
332
333 mdns,
334 mdns_queries: HashMap::new(),
335
336 mdns_mode,
337 mdns_local_name,
338 mdns_local_ip: config.multicast_dns_local_ip,
339
340 ufrag_pwd: UfragPwd::default(),
341
342 local_candidates: vec![],
343 remote_candidates: vec![],
344
345 pending_binding_requests: vec![],
347
348 candidate_types,
349 network_types: config.network_types.clone(),
350 urls: config.urls.clone(),
351
352 write_outs: VecDeque::new(),
353 event_outs: VecDeque::new(),
354 };
355
356 if let Err(err) = agent.restart(config.local_ufrag.clone(), config.local_pwd.clone(), false)
358 {
359 let _ = agent.close();
360 return Err(err);
361 }
362
363 Ok(agent)
364 }
365
366 pub fn add_local_candidate(&mut self, mut c: Candidate) -> Result<bool> {
368 if !self.network_types.is_empty() {
370 let candidate_network_type = c.network_type();
371 if !self.network_types.contains(&candidate_network_type) {
372 debug!(
373 "Ignoring local candidate with network type {:?} (not in configured network types: {:?})",
374 candidate_network_type, self.network_types
375 );
376 return Ok(false);
377 }
378 }
379
380 let candidate_type = c.candidate_type();
382 if !self.candidate_types.is_empty() && !self.candidate_types.contains(&candidate_type) {
383 debug!(
384 "Ignoring local candidate with type {:?} (not in configured candidate types: {:?})",
385 candidate_type, self.candidate_types
386 );
387 return Ok(false);
388 }
389
390 if c.candidate_type() == CandidateType::Host
391 && self.mdns_mode == MulticastDnsMode::QueryAndGather
392 && c.network_type == NetworkType::Udp4
393 && self
394 .mdns_local_ip
395 .is_some_and(|local_ip| local_ip == c.addr().ip())
396 {
397 trace!(
400 "mDNS hides local ip {} with local name {}",
401 c.address, self.mdns_local_name
402 );
403 c.address = self.mdns_local_name.clone();
404 }
405
406 for cand in &self.local_candidates {
407 if cand.equal(&c) {
408 return Ok(false);
409 }
410 }
411
412 self.local_candidates.push(c);
413 let local_index = self.local_candidates.len() - 1;
414 let local_tcp_type = self.local_candidates[local_index].tcp_type();
415
416 for remote_index in 0..self.remote_candidates.len() {
417 let remote_tcp_type = self.remote_candidates[remote_index].tcp_type();
418
419 let should_pair = match (local_tcp_type, remote_tcp_type) {
425 (TcpType::Active, TcpType::Passive) => true,
426 (TcpType::Passive, TcpType::Active) => true,
427 (TcpType::SimultaneousOpen, TcpType::SimultaneousOpen) => true,
428 (TcpType::Unspecified, TcpType::Unspecified) => true, _ => false,
430 };
431
432 if should_pair {
433 self.add_pair(local_index, remote_index);
434 }
435 }
436
437 self.request_connectivity_check();
438
439 Ok(true)
440 }
441
442 pub fn add_remote_candidate(&mut self, c: Candidate) -> Result<bool> {
444 if !self.network_types.is_empty() {
446 let candidate_network_type = c.network_type();
447 if !self.network_types.contains(&candidate_network_type) {
448 debug!(
449 "Ignoring remote candidate with network type {:?} (not in configured network types: {:?})",
450 candidate_network_type, self.network_types
451 );
452 return Ok(false);
453 }
454 }
455
456 if c.tcp_type() == TcpType::Active {
460 debug!(
461 "Ignoring remote candidate with tcptype active: {}",
462 c.address()
463 );
464 return Ok(false);
465 }
466
467 if c.candidate_type() == CandidateType::Host && c.address().ends_with(".local") {
469 if self.mdns_mode == MulticastDnsMode::Disabled {
470 warn!(
471 "remote mDNS candidate added, but mDNS is disabled: ({})",
472 c.address()
473 );
474 return Ok(false);
475 }
476
477 if c.candidate_type() != CandidateType::Host {
478 return Err(Error::ErrAddressParseFailed);
479 }
480
481 if let Some(mdns_conn) = &mut self.mdns {
482 let query_id = mdns_conn.query(c.address());
483 self.mdns_queries.insert(query_id, c);
484 }
485
486 return Ok(false);
487 }
488
489 self.trigger_request_connectivity_check(vec![c]);
490 Ok(true)
491 }
492
493 fn trigger_request_connectivity_check(&mut self, remote_candidates: Vec<Candidate>) {
494 for c in remote_candidates {
495 if !self.remote_candidates.iter().any(|cand| cand.equal(&c)) {
496 let remote_tcp_type = c.tcp_type();
497 self.remote_candidates.push(c);
498 let remote_index = self.remote_candidates.len() - 1;
499
500 for local_index in 0..self.local_candidates.len() {
502 let local_tcp_type = self.local_candidates[local_index].tcp_type();
503
504 let should_pair = match (local_tcp_type, remote_tcp_type) {
510 (TcpType::Active, TcpType::Passive) => true,
511 (TcpType::Passive, TcpType::Active) => true,
512 (TcpType::SimultaneousOpen, TcpType::SimultaneousOpen) => true,
513 (TcpType::Unspecified, TcpType::Unspecified) => true, _ => false,
515 };
516
517 if should_pair {
518 self.add_pair(local_index, remote_index);
519 }
520 }
521
522 self.request_connectivity_check();
523 }
524 }
525 }
526
527 pub fn set_remote_credentials(
529 &mut self,
530 remote_ufrag: String,
531 remote_pwd: String,
532 ) -> Result<()> {
533 if remote_ufrag.is_empty() {
534 return Err(Error::ErrRemoteUfragEmpty);
535 } else if remote_pwd.is_empty() {
536 return Err(Error::ErrRemotePwdEmpty);
537 }
538
539 self.ufrag_pwd.remote_credentials = Some(Credentials {
540 ufrag: remote_ufrag,
541 pwd: remote_pwd,
542 });
543
544 Ok(())
545 }
546
547 pub fn get_remote_credentials(&self) -> Option<&Credentials> {
549 self.ufrag_pwd.remote_credentials.as_ref()
550 }
551
552 pub fn get_local_credentials(&self) -> &Credentials {
554 &self.ufrag_pwd.local_credentials
555 }
556
557 pub fn role(&self) -> bool {
558 self.is_controlling
559 }
560
561 pub fn set_role(&mut self, is_controlling: bool) {
562 self.is_controlling = is_controlling;
563 }
564
565 pub fn state(&self) -> ConnectionState {
566 self.connection_state
567 }
568
569 pub fn is_valid_non_stun_traffic(&mut self, transport: TransportContext) -> bool {
570 self.find_local_candidate(transport.local_addr, transport.transport_protocol)
571 .is_some()
572 && self.validate_non_stun_traffic(transport.peer_addr)
573 }
574
575 fn get_timeout_interval(&self) -> Duration {
576 let (check_interval, keepalive_interval, disconnected_timeout, failed_timeout) = (
577 self.check_interval,
578 self.keepalive_interval,
579 self.disconnected_timeout,
580 self.failed_timeout,
581 );
582 let mut interval = DEFAULT_CHECK_INTERVAL;
583
584 let mut update_interval = |x: Duration| {
585 if x != ZERO_DURATION && (interval == ZERO_DURATION || interval > x) {
586 interval = x;
587 }
588 };
589
590 match self.last_connection_state {
591 ConnectionState::New | ConnectionState::Checking => {
592 update_interval(check_interval);
594 }
595 ConnectionState::Connected | ConnectionState::Disconnected => {
596 update_interval(keepalive_interval);
597 }
598 _ => {}
599 };
600 update_interval(disconnected_timeout);
602 update_interval(failed_timeout);
603 interval
604 }
605
606 pub fn get_selected_candidate_pair(&self) -> Option<(&Candidate, &Candidate)> {
608 if let Some(pair_index) = self.get_selected_pair() {
609 let candidate_pair = &self.candidate_pairs[pair_index];
610 Some((
611 &self.local_candidates[candidate_pair.local_index],
612 &self.remote_candidates[candidate_pair.remote_index],
613 ))
614 } else {
615 None
616 }
617 }
618
619 pub fn get_best_available_candidate_pair(&self) -> Option<(&Candidate, &Candidate)> {
620 if let Some(pair_index) = self.get_best_available_pair() {
621 let candidate_pair = &self.candidate_pairs[pair_index];
622 Some((
623 &self.local_candidates[candidate_pair.local_index],
624 &self.remote_candidates[candidate_pair.remote_index],
625 ))
626 } else {
627 None
628 }
629 }
630
631 pub fn start_connectivity_checks(
633 &mut self,
634 is_controlling: bool,
635 remote_ufrag: String,
636 remote_pwd: String,
637 ) -> Result<()> {
638 debug!(
639 "Started agent: isControlling? {}, remoteUfrag: {}, remotePwd: {}",
640 is_controlling, remote_ufrag, remote_pwd
641 );
642 self.set_remote_credentials(remote_ufrag, remote_pwd)?;
643 self.is_controlling = is_controlling;
644 self.start();
645
646 self.update_connection_state(ConnectionState::Checking);
647 self.request_connectivity_check();
648
649 Ok(())
650 }
651
652 pub fn restart(
655 &mut self,
656 mut ufrag: String,
657 mut pwd: String,
658 keep_local_candidates: bool,
659 ) -> Result<()> {
660 if ufrag.is_empty() {
661 ufrag = generate_ufrag();
662 }
663 if pwd.is_empty() {
664 pwd = generate_pwd();
665 }
666
667 if ufrag.len() * 8 < 24 {
668 return Err(Error::ErrLocalUfragInsufficientBits);
669 }
670 if pwd.len() * 8 < 128 {
671 return Err(Error::ErrLocalPwdInsufficientBits);
672 }
673
674 self.ufrag_pwd.local_credentials.ufrag = ufrag;
676 self.ufrag_pwd.local_credentials.pwd = pwd;
677 self.ufrag_pwd.remote_credentials = None;
678
679 self.pending_binding_requests = vec![];
680
681 self.candidate_pairs = vec![];
682
683 self.set_selected_pair(None);
684 self.delete_all_candidates(keep_local_candidates);
685 self.start();
686
687 if self.connection_state != ConnectionState::New {
690 self.update_connection_state(ConnectionState::Checking);
691 }
692
693 Ok(())
694 }
695
696 pub fn get_local_candidates(&self) -> &[Candidate] {
698 &self.local_candidates
699 }
700
701 fn contact(&mut self, now: Instant) {
702 if self.connection_state == ConnectionState::Failed {
703 self.last_connection_state = self.connection_state;
706 return;
707 }
708 if self.connection_state == ConnectionState::Checking {
709 if self.last_connection_state != self.connection_state {
711 self.checking_duration = now;
712 }
713
714 if now
716 .checked_duration_since(self.checking_duration)
717 .unwrap_or_else(|| Duration::from_secs(0))
718 > self.disconnected_timeout + self.failed_timeout
719 {
720 self.update_connection_state(ConnectionState::Failed);
721 self.last_connection_state = self.connection_state;
722 return;
723 }
724 }
725
726 self.contact_candidates();
727
728 self.last_connection_state = self.connection_state;
729 self.last_checking_time = now;
730 }
731
732 pub(crate) fn update_connection_state(&mut self, new_state: ConnectionState) {
733 if self.connection_state != new_state {
734 if new_state == ConnectionState::Failed {
736 self.set_selected_pair(None);
737 self.delete_all_candidates(false);
738 }
739
740 info!(
741 "[{}]: Setting new connection state: {}",
742 self.get_name(),
743 new_state
744 );
745 self.connection_state = new_state;
746 self.event_outs
747 .push_back(Event::ConnectionStateChange(new_state));
748 }
749 }
750
751 pub(crate) fn set_selected_pair(&mut self, selected_pair: Option<usize>) {
752 if let Some(pair_index) = selected_pair {
753 trace!(
754 "[{}]: Set selected candidate pair: {:?}",
755 self.get_name(),
756 self.candidate_pairs[pair_index]
757 );
758
759 self.candidate_pairs[pair_index].nominated = true;
760 self.selected_pair = Some(pair_index);
761
762 self.update_connection_state(ConnectionState::Connected);
763
764 let candidate_pair = &self.candidate_pairs[pair_index];
766 self.event_outs
767 .push_back(Event::SelectedCandidatePairChange(
768 Box::new(self.local_candidates[candidate_pair.local_index].clone()),
769 Box::new(self.remote_candidates[candidate_pair.remote_index].clone()),
770 ));
771 } else {
772 self.selected_pair = None;
773 }
774 }
775
776 pub(crate) fn ping_all_candidates(&mut self) {
777 let mut pairs: Vec<(usize, usize)> = vec![];
778
779 let name = self.get_name().to_string();
780 if self.candidate_pairs.is_empty() {
781 warn!(
782 "[{}]: pingAllCandidates called with no candidate pairs. Connection is not possible yet.",
783 name,
784 );
785 }
786 for p in &mut self.candidate_pairs {
787 if p.state == CandidatePairState::Waiting {
788 p.state = CandidatePairState::InProgress;
789 } else if p.state != CandidatePairState::InProgress {
790 continue;
791 }
792
793 if p.binding_request_count > self.max_binding_requests {
794 trace!(
795 "[{}]: max requests reached for pair {} (local_addr {} <-> remote_addr {}), marking it as failed",
796 name,
797 *p,
798 self.local_candidates[p.local_index].addr(),
799 self.remote_candidates[p.remote_index].addr()
800 );
801 p.state = CandidatePairState::Failed;
802 } else {
803 p.binding_request_count += 1;
804 let local = p.local_index;
805 let remote = p.remote_index;
806 pairs.push((local, remote));
807 }
808 }
809
810 if !pairs.is_empty() {
811 trace!(
812 "[{}]: pinging all {} candidates",
813 self.get_name(),
814 pairs.len()
815 );
816 }
817
818 for (local, remote) in pairs {
819 self.ping_candidate(local, remote);
820 }
821 }
822
823 pub(crate) fn add_pair(&mut self, local_index: usize, remote_index: usize) {
824 let p = CandidatePair::new(
825 local_index,
826 remote_index,
827 self.local_candidates[local_index].priority(),
828 self.remote_candidates[remote_index].priority(),
829 self.is_controlling,
830 );
831 self.candidate_pairs.push(p);
832 }
833
834 pub(crate) fn find_pair(&self, local_index: usize, remote_index: usize) -> Option<usize> {
835 for (index, p) in self.candidate_pairs.iter().enumerate() {
836 if p.local_index == local_index && p.remote_index == remote_index {
837 return Some(index);
838 }
839 }
840 None
841 }
842
843 pub(crate) fn validate_selected_pair(&mut self) -> bool {
846 let (valid, disconnected_time) = {
847 self.selected_pair.as_ref().map_or_else(
848 || (false, Duration::from_secs(0)),
849 |&pair_index| {
850 let remote_index = self.candidate_pairs[pair_index].remote_index;
851
852 let disconnected_time = Instant::now()
853 .duration_since(self.remote_candidates[remote_index].last_received());
854 (true, disconnected_time)
855 },
856 )
857 };
858
859 if valid {
860 let mut total_time_to_failure = self.failed_timeout;
862 if total_time_to_failure != Duration::from_secs(0) {
863 total_time_to_failure += self.disconnected_timeout;
864 }
865
866 if total_time_to_failure != Duration::from_secs(0)
867 && disconnected_time > total_time_to_failure
868 {
869 self.update_connection_state(ConnectionState::Failed);
870 } else if self.disconnected_timeout != Duration::from_secs(0)
871 && disconnected_time > self.disconnected_timeout
872 {
873 self.update_connection_state(ConnectionState::Disconnected);
874 } else {
875 self.update_connection_state(ConnectionState::Connected);
876 }
877 }
878
879 valid
880 }
881
882 pub(crate) fn check_keepalive(&mut self) {
885 let (local_index, remote_index, pair_index) = {
886 self.selected_pair
887 .as_ref()
888 .map_or((None, None, None), |&pair_index| {
889 let p = &self.candidate_pairs[pair_index];
890 (Some(p.local_index), Some(p.remote_index), Some(pair_index))
891 })
892 };
893
894 if let (Some(local_index), Some(remote_index), Some(pair_index)) =
895 (local_index, remote_index, pair_index)
896 && self.keepalive_interval != Duration::from_secs(0)
897 && self.last_consent_sent.elapsed() >= self.keepalive_interval
898 {
899 self.last_consent_sent = Instant::now();
900 self.candidate_pairs[pair_index].on_consent_request_sent();
901 self.ping_candidate(local_index, remote_index);
902 }
903 }
904
905 fn request_connectivity_check(&mut self) {
906 if self.ufrag_pwd.remote_credentials.is_some() {
907 self.contact(Instant::now());
908 }
909 }
910
911 pub(crate) fn delete_all_candidates(&mut self, keep_local_candidates: bool) {
916 if !keep_local_candidates {
917 self.local_candidates.clear();
918 }
919 self.remote_candidates.clear();
920 }
921
922 pub(crate) fn find_remote_candidate(&self, addr: SocketAddr) -> Option<usize> {
923 for (index, c) in self.remote_candidates.iter().enumerate() {
924 if c.addr() == addr {
925 return Some(index);
926 }
927 }
928 None
929 }
930
931 pub(crate) fn find_local_candidate(
932 &self,
933 addr: SocketAddr,
934 transport_protocol: TransportProtocol,
935 ) -> Option<usize> {
936 for (index, c) in self.local_candidates.iter().enumerate() {
937 if c.network_type().to_protocol() != transport_protocol {
938 continue;
939 }
940
941 if c.tcp_type() == TcpType::Active && transport_protocol == TransportProtocol::TCP {
945 if c.addr().ip() == addr.ip() {
946 return Some(index);
947 }
948 } else if c.addr() == addr {
949 return Some(index);
950 } else if let Some(related_address) = c.related_address()
951 && related_address.address == addr.ip().to_string()
952 && related_address.port == addr.port()
953 {
954 return Some(index);
955 }
956 }
957 None
958 }
959
960 pub(crate) fn send_binding_request(
961 &mut self,
962 m: &Message,
963 local_index: usize,
964 remote_index: usize,
965 ) {
966 trace!(
967 "[{}]: ping STUN from {} to {}",
968 self.get_name(),
969 self.local_candidates[local_index],
970 self.remote_candidates[remote_index],
971 );
972
973 self.invalidate_pending_binding_requests(Instant::now());
974
975 self.pending_binding_requests.push(BindingRequest {
976 timestamp: Instant::now(),
977 transaction_id: m.transaction_id,
978 destination: self.remote_candidates[remote_index].addr(),
979 is_use_candidate: m.contains(ATTR_USE_CANDIDATE),
980 });
981
982 if let Some(pair_index) = self.find_pair(local_index, remote_index) {
984 self.candidate_pairs[pair_index].on_request_sent();
985 }
986
987 self.send_stun(m, local_index, remote_index);
988 }
989
990 pub(crate) fn send_binding_success(
991 &mut self,
992 m: &Message,
993 local_index: usize,
994 remote_index: usize,
995 ) {
996 let addr = self.remote_candidates[remote_index].addr();
997 let (ip, port) = (addr.ip(), addr.port());
998 let local_pwd = self.ufrag_pwd.local_credentials.pwd.clone();
999
1000 let (out, result) = {
1001 let mut out = Message::new();
1002 let result = out.build(&[
1003 Box::new(m.clone()),
1004 Box::new(BINDING_SUCCESS),
1005 Box::new(XorMappedAddress { ip, port }),
1006 Box::new(MessageIntegrity::new_short_term_integrity(local_pwd)),
1007 Box::new(FINGERPRINT),
1008 ]);
1009 (out, result)
1010 };
1011
1012 if let Err(err) = result {
1013 warn!(
1014 "[{}]: Failed to handle inbound ICE from: {} to: {} error: {}",
1015 self.get_name(),
1016 self.local_candidates[local_index],
1017 self.remote_candidates[remote_index],
1018 err
1019 );
1020 } else {
1021 if let Some(pair_index) = self.find_pair(local_index, remote_index) {
1023 self.candidate_pairs[pair_index].on_response_sent();
1024 }
1025 self.send_stun(&out, local_index, remote_index);
1026 }
1027 }
1028
1029 pub(crate) fn send_role_conflict_error(
1032 &mut self,
1033 m: &Message,
1034 local_index: usize,
1035 remote_index: usize,
1036 ) {
1037 use stun::error_code::*;
1038
1039 let local_pwd = self.ufrag_pwd.local_credentials.pwd.clone();
1040
1041 let (out, result) = {
1042 let mut out = Message::new();
1043 let result = out.build(&[
1044 Box::new(m.clone()),
1045 Box::new(stun::message::BINDING_ERROR),
1046 Box::new(CODE_ROLE_CONFLICT),
1047 Box::new(MessageIntegrity::new_short_term_integrity(local_pwd)),
1048 Box::new(FINGERPRINT),
1049 ]);
1050 (out, result)
1051 };
1052
1053 if let Err(err) = result {
1054 warn!(
1055 "[{}]: Failed to send role conflict error from: {} to: {} error: {}",
1056 self.get_name(),
1057 self.local_candidates[local_index],
1058 self.remote_candidates[remote_index],
1059 err
1060 );
1061 } else {
1062 debug!(
1063 "[{}]: Sent 487 Role Conflict error from {} to {}",
1064 self.get_name(),
1065 self.local_candidates[local_index],
1066 self.remote_candidates[remote_index]
1067 );
1068 self.send_stun(&out, local_index, remote_index);
1069 }
1070 }
1071
1072 pub(crate) fn switch_role(&mut self) {
1075 self.is_controlling = !self.is_controlling;
1076
1077 for pair in &mut self.candidate_pairs {
1080 pair.ice_role_controlling = self.is_controlling;
1081 }
1082
1083 self.nominated_pair = None;
1085
1086 info!(
1087 "[{}]: Role switched, recomputed {} candidate pair priorities",
1088 self.get_name(),
1089 self.candidate_pairs.len()
1090 );
1091
1092 self.event_outs
1093 .push_back(Event::RoleChange(self.is_controlling));
1094 }
1095
1096 pub(crate) fn invalidate_pending_binding_requests(&mut self, filter_time: Instant) {
1101 let pending_binding_requests = &mut self.pending_binding_requests;
1102 let initial_size = pending_binding_requests.len();
1103
1104 let mut temp = vec![];
1105 for binding_request in pending_binding_requests.drain(..) {
1106 if filter_time
1107 .checked_duration_since(binding_request.timestamp)
1108 .map(|duration| duration < MAX_BINDING_REQUEST_TIMEOUT)
1109 .unwrap_or(true)
1110 {
1111 temp.push(binding_request);
1112 }
1113 }
1114
1115 *pending_binding_requests = temp;
1116 let bind_requests_remaining = pending_binding_requests.len();
1117 let bind_requests_removed = initial_size - bind_requests_remaining;
1118 if bind_requests_removed > 0 {
1119 trace!(
1120 "[{}]: Discarded {} binding requests because they expired, still {} remaining",
1121 self.get_name(),
1122 bind_requests_removed,
1123 bind_requests_remaining,
1124 );
1125 }
1126 }
1127
1128 pub(crate) fn handle_inbound_binding_success(
1131 &mut self,
1132 id: TransactionId,
1133 ) -> Option<BindingRequest> {
1134 self.invalidate_pending_binding_requests(Instant::now());
1135
1136 let pending_binding_requests = &mut self.pending_binding_requests;
1137 for i in 0..pending_binding_requests.len() {
1138 if pending_binding_requests[i].transaction_id == id {
1139 let valid_binding_request = pending_binding_requests.remove(i);
1140 return Some(valid_binding_request);
1141 }
1142 }
1143 None
1144 }
1145
1146 pub(crate) fn handle_inbound(
1148 &mut self,
1149 now: Instant,
1150 m: &mut Message,
1151 local_index: usize,
1152 remote_addr: SocketAddr,
1153 ) -> Result<()> {
1154 if m.typ.method != METHOD_BINDING
1155 || !(m.typ.class == CLASS_SUCCESS_RESPONSE
1156 || m.typ.class == CLASS_REQUEST
1157 || m.typ.class == CLASS_INDICATION)
1158 {
1159 trace!(
1160 "[{}]: unhandled STUN from {} to {} class({}) method({})",
1161 self.get_name(),
1162 remote_addr,
1163 self.local_candidates[local_index],
1164 m.typ.class,
1165 m.typ.method
1166 );
1167 return Err(Error::ErrUnhandledStunpacket);
1168 }
1169
1170 if self.is_controlling {
1172 if m.contains(ATTR_ICE_CONTROLLING) {
1173 let mut remote_controlling = crate::attributes::control::AttrControlling::default();
1175 if let Err(err) = remote_controlling.get_from(m) {
1176 warn!(
1177 "[{}]: Failed to get remote ICE-CONTROLLING attribute: {}",
1178 self.get_name(),
1179 err
1180 );
1181 return Err(err);
1182 }
1183
1184 debug!(
1185 "[{}]: Role conflict detected (both controlling), local tiebreaker: {}, remote tiebreaker: {}",
1186 self.get_name(),
1187 self.tie_breaker,
1188 remote_controlling.0
1189 );
1190
1191 if m.typ.class == CLASS_REQUEST {
1193 if let Some(remote_index) = self.find_remote_candidate(remote_addr) {
1195 self.send_role_conflict_error(m, local_index, remote_index);
1196 }
1197
1198 if self.tie_breaker < remote_controlling.0 {
1200 info!(
1201 "[{}]: Switching from controlling to controlled due to role conflict (smaller tiebreaker)",
1202 self.get_name()
1203 );
1204 self.switch_role();
1205 }
1206 }
1207 } else if m.contains(ATTR_USE_CANDIDATE) {
1209 debug!(
1210 "[{}]: useCandidate && a.isControlling == true",
1211 self.get_name(),
1212 );
1213 return Err(Error::ErrUnexpectedStunrequestMessage);
1214 }
1215 } else if m.contains(ATTR_ICE_CONTROLLED) {
1216 let mut remote_controlled = crate::attributes::control::AttrControlled::default();
1218 if let Err(err) = remote_controlled.get_from(m) {
1219 warn!(
1220 "[{}]: Failed to get remote ICE-CONTROLLED attribute: {}",
1221 self.get_name(),
1222 err
1223 );
1224 return Err(err);
1225 }
1226
1227 debug!(
1228 "[{}]: Role conflict detected (both controlled), local tiebreaker: {}, remote tiebreaker: {}",
1229 self.get_name(),
1230 self.tie_breaker,
1231 remote_controlled.0
1232 );
1233
1234 if m.typ.class == CLASS_REQUEST {
1236 if let Some(remote_index) = self.find_remote_candidate(remote_addr) {
1238 self.send_role_conflict_error(m, local_index, remote_index);
1239 }
1240
1241 if self.tie_breaker > remote_controlled.0 {
1243 info!(
1244 "[{}]: Switching from controlled to controlling due to role conflict (larger tiebreaker)",
1245 self.get_name()
1246 );
1247 self.switch_role();
1248 }
1249 }
1250 }
1252
1253 let Some(remote_credentials) = &self.ufrag_pwd.remote_credentials else {
1254 debug!(
1255 "[{}]: ufrag_pwd.remote_credentials.is_none",
1256 self.get_name(),
1257 );
1258 return Err(Error::ErrPasswordEmpty);
1259 };
1260
1261 let mut remote_candidate_index = self.find_remote_candidate(remote_addr);
1262 if m.typ.class == CLASS_SUCCESS_RESPONSE {
1263 if let Err(err) = assert_inbound_message_integrity(m, remote_credentials.pwd.as_bytes())
1264 {
1265 warn!(
1266 "[{}]: discard message from ({}), {}",
1267 self.get_name(),
1268 remote_addr,
1269 err
1270 );
1271 return Err(err);
1272 }
1273
1274 if let Some(remote_index) = &remote_candidate_index {
1275 self.handle_success_response(now, m, local_index, *remote_index, remote_addr);
1276 } else {
1277 warn!(
1278 "[{}]: discard success message from ({}), no such remote",
1279 self.get_name(),
1280 remote_addr
1281 );
1282 return Err(Error::ErrUnhandledStunpacket);
1283 }
1284 } else if m.typ.class == CLASS_REQUEST {
1285 {
1286 let username = self.ufrag_pwd.local_credentials.ufrag.clone()
1287 + ":"
1288 + remote_credentials.ufrag.as_str();
1289 if let Err(err) = assert_inbound_username(m, &username) {
1290 warn!(
1291 "[{}]: discard message from ({}), {}",
1292 self.get_name(),
1293 remote_addr,
1294 err
1295 );
1296 return Err(err);
1297 } else if let Err(err) = assert_inbound_message_integrity(
1298 m,
1299 self.ufrag_pwd.local_credentials.pwd.as_bytes(),
1300 ) {
1301 warn!(
1302 "[{}]: discard message from ({}), {}",
1303 self.get_name(),
1304 remote_addr,
1305 err
1306 );
1307 return Err(err);
1308 }
1309 }
1310
1311 if remote_candidate_index.is_none() {
1312 let network_type = self.local_candidates[local_index].network_type();
1314 let (ip, port) = (remote_addr.ip(), remote_addr.port());
1315
1316 let prflx_candidate_config = CandidatePeerReflexiveConfig {
1317 base_config: CandidateConfig {
1318 network: network_type.to_string(),
1319 address: ip.to_string(),
1320 port,
1321 component: self.local_candidates[local_index].component(),
1322 ..CandidateConfig::default()
1323 },
1324 rel_addr: "".to_owned(),
1325 rel_port: 0,
1326 };
1327
1328 match prflx_candidate_config.new_candidate_peer_reflexive() {
1329 Ok(prflx_candidate) => {
1330 if let Ok(added) = self.add_remote_candidate(prflx_candidate)
1331 && added
1332 {
1333 remote_candidate_index = Some(self.remote_candidates.len() - 1);
1334 }
1335 }
1336 Err(err) => {
1337 error!(
1338 "[{}]: Failed to create new remote prflx candidate ({})",
1339 self.get_name(),
1340 err
1341 );
1342 return Err(err);
1343 }
1344 };
1345
1346 debug!(
1347 "[{}]: adding a new peer-reflexive candidate: {} ",
1348 self.get_name(),
1349 remote_addr
1350 );
1351 }
1352
1353 trace!(
1354 "[{}]: inbound STUN (Request) from {} to {}",
1355 self.get_name(),
1356 remote_addr,
1357 self.local_candidates[local_index]
1358 );
1359
1360 if let Some(remote_index) = &remote_candidate_index {
1361 self.handle_binding_request(m, local_index, *remote_index);
1362 }
1363 }
1364
1365 if let Some(remote_index) = remote_candidate_index {
1366 self.remote_candidates[remote_index].seen(false);
1367 }
1368
1369 Ok(())
1370 }
1371
1372 pub(crate) fn validate_non_stun_traffic(&mut self, remote_addr: SocketAddr) -> bool {
1375 self.find_remote_candidate(remote_addr)
1376 .is_some_and(|remote_index| {
1377 self.remote_candidates[remote_index].seen(false);
1378 true
1379 })
1380 }
1381
1382 pub(crate) fn send_stun(&mut self, msg: &Message, local_index: usize, remote_index: usize) {
1383 let peer_addr = self.remote_candidates[remote_index].addr();
1384 let local_addr = self.local_candidates[local_index].addr();
1385 let transport_protocol = if self.local_candidates[local_index].network_type().is_tcp() {
1386 TransportProtocol::TCP
1387 } else {
1388 TransportProtocol::UDP
1389 };
1390
1391 self.write_outs.push_back(TaggedBytesMut {
1392 now: Instant::now(),
1393 transport: TransportContext {
1394 local_addr,
1395 peer_addr,
1396 ecn: None,
1397 transport_protocol,
1398 },
1399 message: BytesMut::from(&msg.raw[..]),
1400 });
1401
1402 self.local_candidates[local_index].seen(true);
1403 }
1404
1405 fn handle_inbound_candidate_msg(
1406 &mut self,
1407 local_index: usize,
1408 msg: TaggedBytesMut,
1409 ) -> Result<()> {
1410 if is_stun_message(&msg.message) {
1411 let mut m = Message {
1412 raw: msg.message.to_vec(),
1413 ..Message::default()
1414 };
1415
1416 if let Err(err) = m.decode() {
1417 warn!(
1418 "[{}]: Failed to handle decode ICE from {} to {}: {}",
1419 self.get_name(),
1420 msg.transport.local_addr,
1421 msg.transport.peer_addr,
1422 err
1423 );
1424 Err(err)
1425 } else {
1426 self.handle_inbound(msg.now, &mut m, local_index, msg.transport.peer_addr)
1427 }
1428 } else {
1429 if !self.validate_non_stun_traffic(msg.transport.peer_addr) {
1430 warn!(
1431 "[{}]: Discarded message, not a valid remote candidate from {}",
1432 self.get_name(),
1433 msg.transport.peer_addr,
1434 );
1435 } else {
1436 warn!(
1437 "[{}]: non-STUN traffic message from a valid remote candidate from {}",
1438 self.get_name(),
1439 msg.transport.peer_addr
1440 );
1441 }
1442 Err(Error::ErrNonStunmessage)
1443 }
1444 }
1445
1446 pub(crate) fn get_name(&self) -> &str {
1447 if self.is_controlling {
1448 "controlling"
1449 } else {
1450 "controlled"
1451 }
1452 }
1453
1454 pub(crate) fn get_selected_pair(&self) -> Option<usize> {
1455 self.selected_pair
1456 }
1457
1458 pub(crate) fn get_best_available_pair(&self) -> Option<usize> {
1459 let mut best_pair_index: Option<usize> = None;
1460
1461 for (index, p) in self.candidate_pairs.iter().enumerate() {
1462 if p.state == CandidatePairState::Failed {
1463 continue;
1464 }
1465
1466 if let Some(pair_index) = &mut best_pair_index {
1467 let b = &self.candidate_pairs[*pair_index];
1468 if b.priority() < p.priority() {
1469 *pair_index = index;
1470 }
1471 } else {
1472 best_pair_index = Some(index);
1473 }
1474 }
1475
1476 best_pair_index
1477 }
1478
1479 pub(crate) fn get_best_valid_candidate_pair(&self) -> Option<usize> {
1480 let mut best_pair_index: Option<usize> = None;
1481
1482 for (index, p) in self.candidate_pairs.iter().enumerate() {
1483 if p.state != CandidatePairState::Succeeded {
1484 continue;
1485 }
1486
1487 if let Some(pair_index) = &mut best_pair_index {
1488 let b = &self.candidate_pairs[*pair_index];
1489 if b.priority() < p.priority() {
1490 *pair_index = index;
1491 }
1492 } else {
1493 best_pair_index = Some(index);
1494 }
1495 }
1496
1497 best_pair_index
1498 }
1499}