1 #[cfg(test)] 2 mod agent_gather_test; 3 #[cfg(test)] 4 mod agent_test; 5 #[cfg(test)] 6 mod agent_transport_test; 7 #[cfg(test)] 8 pub(crate) mod agent_vnet_test; 9 10 pub mod agent_config; 11 pub mod agent_gather; 12 pub(crate) mod agent_internal; 13 pub mod agent_selector; 14 pub mod agent_stats; 15 pub mod agent_transport; 16 17 use crate::candidate::*; 18 use crate::error::*; 19 use crate::external_ip_mapper::*; 20 use crate::mdns::*; 21 use crate::network_type::*; 22 use crate::state::*; 23 use crate::udp_mux::UDPMux; 24 use crate::udp_network::UDPNetwork; 25 use crate::url::*; 26 use agent_config::*; 27 use agent_internal::*; 28 use agent_stats::*; 29 30 use mdns::conn::*; 31 use std::collections::HashMap; 32 use std::net::{Ipv4Addr, SocketAddr}; 33 use stun::{agent::*, attributes::*, fingerprint::*, integrity::*, message::*, xoraddr::*}; 34 use util::{vnet::net::*, Buffer}; 35 36 use crate::agent::agent_gather::GatherCandidatesInternalParams; 37 use crate::rand::*; 38 use crate::tcp_type::TcpType; 39 use std::future::Future; 40 use std::pin::Pin; 41 use std::sync::atomic::{AtomicU8, AtomicUsize, Ordering}; 42 use std::sync::Arc; 43 use std::time::SystemTime; 44 use tokio::sync::{broadcast, mpsc, Mutex}; 45 use tokio::time::{Duration, Instant}; 46 47 #[derive(Debug, Clone)] 48 pub(crate) struct BindingRequest { 49 pub(crate) timestamp: Instant, 50 pub(crate) transaction_id: TransactionId, 51 pub(crate) destination: SocketAddr, 52 pub(crate) is_use_candidate: bool, 53 } 54 55 impl Default for BindingRequest { 56 fn default() -> Self { 57 Self { 58 timestamp: Instant::now(), 59 transaction_id: TransactionId::default(), 60 destination: SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 0), 61 is_use_candidate: false, 62 } 63 } 64 } 65 66 pub type OnConnectionStateChangeHdlrFn = Box< 67 dyn (FnMut(ConnectionState) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>>) 68 + Send 69 + Sync, 70 >; 71 pub type OnSelectedCandidatePairChangeHdlrFn = Box< 72 dyn (FnMut( 73 &Arc<dyn Candidate + Send + Sync>, 74 &Arc<dyn Candidate + Send + Sync>, 75 ) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>>) 76 + Send 77 + Sync, 78 >; 79 pub type OnCandidateHdlrFn = Box< 80 dyn (FnMut( 81 Option<Arc<dyn Candidate + Send + Sync>>, 82 ) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>>) 83 + Send 84 + Sync, 85 >; 86 pub type GatherCandidateCancelFn = Box<dyn Fn() + Send + Sync>; 87 88 struct ChanReceivers { 89 chan_state_rx: mpsc::Receiver<ConnectionState>, 90 chan_candidate_rx: mpsc::Receiver<Option<Arc<dyn Candidate + Send + Sync>>>, 91 chan_candidate_pair_rx: mpsc::Receiver<()>, 92 } 93 94 /// Represents the ICE agent. 95 pub struct Agent { 96 pub(crate) internal: Arc<AgentInternal>, 97 98 pub(crate) udp_network: UDPNetwork, 99 pub(crate) interface_filter: Arc<Option<InterfaceFilterFn>>, 100 pub(crate) ip_filter: Arc<Option<IpFilterFn>>, 101 pub(crate) mdns_mode: MulticastDnsMode, 102 pub(crate) mdns_name: String, 103 pub(crate) mdns_conn: Option<Arc<DnsConn>>, 104 pub(crate) net: Arc<Net>, 105 106 // 1:1 D-NAT IP address mapping 107 pub(crate) ext_ip_mapper: Arc<Option<ExternalIpMapper>>, 108 pub(crate) gathering_state: Arc<AtomicU8>, //GatheringState, 109 pub(crate) candidate_types: Vec<CandidateType>, 110 pub(crate) urls: Vec<Url>, 111 pub(crate) network_types: Vec<NetworkType>, 112 113 pub(crate) gather_candidate_cancel: Option<GatherCandidateCancelFn>, 114 } 115 116 impl Agent { 117 /// Creates a new Agent. 118 pub async fn new(config: AgentConfig) -> Result<Self> { 119 let mut mdns_name = config.multicast_dns_host_name.clone(); 120 if mdns_name.is_empty() { 121 mdns_name = generate_multicast_dns_name(); 122 } 123 124 if !mdns_name.ends_with(".local") || mdns_name.split('.').count() != 2 { 125 return Err(Error::ErrInvalidMulticastDnshostName); 126 } 127 128 let mut mdns_mode = config.multicast_dns_mode; 129 if mdns_mode == MulticastDnsMode::Unspecified { 130 mdns_mode = MulticastDnsMode::QueryOnly; 131 } 132 133 let mdns_conn = 134 match create_multicast_dns(mdns_mode, &mdns_name, &config.multicast_dns_dest_addr) { 135 Ok(c) => c, 136 Err(err) => { 137 // Opportunistic mDNS: If we can't open the connection, that's ok: we 138 // can continue without it. 139 log::warn!("Failed to initialize mDNS {}: {}", mdns_name, err); 140 None 141 } 142 }; 143 144 let (mut ai, chan_receivers) = AgentInternal::new(&config); 145 let (chan_state_rx, chan_candidate_rx, chan_candidate_pair_rx) = ( 146 chan_receivers.chan_state_rx, 147 chan_receivers.chan_candidate_rx, 148 chan_receivers.chan_candidate_pair_rx, 149 ); 150 151 config.init_with_defaults(&mut ai); 152 153 let candidate_types = if config.candidate_types.is_empty() { 154 default_candidate_types() 155 } else { 156 config.candidate_types.clone() 157 }; 158 159 if ai.lite.load(Ordering::SeqCst) 160 && (candidate_types.len() != 1 || candidate_types[0] != CandidateType::Host) 161 { 162 Self::close_multicast_conn(&mdns_conn).await; 163 return Err(Error::ErrLiteUsingNonHostCandidates); 164 } 165 166 if !config.urls.is_empty() 167 && !contains_candidate_type(CandidateType::ServerReflexive, &candidate_types) 168 && !contains_candidate_type(CandidateType::Relay, &candidate_types) 169 { 170 Self::close_multicast_conn(&mdns_conn).await; 171 return Err(Error::ErrUselessUrlsProvided); 172 } 173 174 let ext_ip_mapper = match config.init_ext_ip_mapping(mdns_mode, &candidate_types) { 175 Ok(ext_ip_mapper) => ext_ip_mapper, 176 Err(err) => { 177 Self::close_multicast_conn(&mdns_conn).await; 178 return Err(err); 179 } 180 }; 181 182 let net = if let Some(net) = config.net { 183 if net.is_virtual() { 184 log::warn!("vnet is enabled"); 185 if mdns_mode != MulticastDnsMode::Disabled { 186 log::warn!("vnet does not support mDNS yet"); 187 } 188 } 189 190 net 191 } else { 192 Arc::new(Net::new(None)) 193 }; 194 195 let agent = Self { 196 udp_network: config.udp_network, 197 internal: Arc::new(ai), 198 interface_filter: Arc::clone(&config.interface_filter), 199 ip_filter: Arc::clone(&config.ip_filter), 200 mdns_mode, 201 mdns_name, 202 mdns_conn, 203 net, 204 ext_ip_mapper: Arc::new(ext_ip_mapper), 205 gathering_state: Arc::new(AtomicU8::new(0)), //GatheringState::New, 206 candidate_types, 207 urls: config.urls.clone(), 208 network_types: config.network_types.clone(), 209 210 gather_candidate_cancel: None, //TODO: add cancel 211 }; 212 213 agent.internal.start_on_connection_state_change_routine( 214 chan_state_rx, 215 chan_candidate_rx, 216 chan_candidate_pair_rx, 217 ); 218 219 // Restart is also used to initialize the agent for the first time 220 if let Err(err) = agent.restart(config.local_ufrag, config.local_pwd).await { 221 Self::close_multicast_conn(&agent.mdns_conn).await; 222 let _ = agent.close().await; 223 return Err(err); 224 } 225 226 Ok(agent) 227 } 228 229 pub fn get_bytes_received(&self) -> usize { 230 self.internal.agent_conn.bytes_received() 231 } 232 233 pub fn get_bytes_sent(&self) -> usize { 234 self.internal.agent_conn.bytes_sent() 235 } 236 237 /// Sets a handler that is fired when the connection state changes. 238 pub fn on_connection_state_change(&self, f: OnConnectionStateChangeHdlrFn) { 239 self.internal 240 .on_connection_state_change_hdlr 241 .store(Some(Arc::new(Mutex::new(f)))) 242 } 243 244 /// Sets a handler that is fired when the final candidate pair is selected. 245 pub fn on_selected_candidate_pair_change(&self, f: OnSelectedCandidatePairChangeHdlrFn) { 246 self.internal 247 .on_selected_candidate_pair_change_hdlr 248 .store(Some(Arc::new(Mutex::new(f)))) 249 } 250 251 /// Sets a handler that is fired when new candidates gathered. When the gathering process 252 /// complete the last candidate is nil. 253 pub fn on_candidate(&self, f: OnCandidateHdlrFn) { 254 self.internal 255 .on_candidate_hdlr 256 .store(Some(Arc::new(Mutex::new(f)))); 257 } 258 259 /// Adds a new remote candidate. 260 pub fn add_remote_candidate(&self, c: &Arc<dyn Candidate + Send + Sync>) -> Result<()> { 261 // cannot check for network yet because it might not be applied 262 // when mDNS hostame is used. 263 if c.tcp_type() == TcpType::Active { 264 // TCP Candidates with tcptype active will probe server passive ones, so 265 // no need to do anything with them. 266 log::info!("Ignoring remote candidate with tcpType active: {}", c); 267 return Ok(()); 268 } 269 270 // If we have a mDNS Candidate lets fully resolve it before adding it locally 271 if c.candidate_type() == CandidateType::Host && c.address().ends_with(".local") { 272 if self.mdns_mode == MulticastDnsMode::Disabled { 273 log::warn!( 274 "remote mDNS candidate added, but mDNS is disabled: ({})", 275 c.address() 276 ); 277 return Ok(()); 278 } 279 280 if c.candidate_type() != CandidateType::Host { 281 return Err(Error::ErrAddressParseFailed); 282 } 283 284 let ai = Arc::clone(&self.internal); 285 let host_candidate = Arc::clone(c); 286 let mdns_conn = self.mdns_conn.clone(); 287 tokio::spawn(async move { 288 if let Some(mdns_conn) = mdns_conn { 289 if let Ok(candidate) = 290 Self::resolve_and_add_multicast_candidate(mdns_conn, host_candidate).await 291 { 292 ai.add_remote_candidate(&candidate).await; 293 } 294 } 295 }); 296 } else { 297 let ai = Arc::clone(&self.internal); 298 let candidate = Arc::clone(c); 299 tokio::spawn(async move { 300 ai.add_remote_candidate(&candidate).await; 301 }); 302 } 303 304 Ok(()) 305 } 306 307 /// Returns the local candidates. 308 pub async fn get_local_candidates(&self) -> Result<Vec<Arc<dyn Candidate + Send + Sync>>> { 309 let mut res = vec![]; 310 311 { 312 let local_candidates = self.internal.local_candidates.lock().await; 313 for candidates in local_candidates.values() { 314 for candidate in candidates { 315 res.push(Arc::clone(candidate)); 316 } 317 } 318 } 319 320 Ok(res) 321 } 322 323 /// Returns the local user credentials. 324 pub async fn get_local_user_credentials(&self) -> (String, String) { 325 let ufrag_pwd = self.internal.ufrag_pwd.lock().await; 326 (ufrag_pwd.local_ufrag.clone(), ufrag_pwd.local_pwd.clone()) 327 } 328 329 /// Returns the remote user credentials. 330 pub async fn get_remote_user_credentials(&self) -> (String, String) { 331 let ufrag_pwd = self.internal.ufrag_pwd.lock().await; 332 (ufrag_pwd.remote_ufrag.clone(), ufrag_pwd.remote_pwd.clone()) 333 } 334 335 /// Cleans up the Agent. 336 pub async fn close(&self) -> Result<()> { 337 if let Some(gather_candidate_cancel) = &self.gather_candidate_cancel { 338 gather_candidate_cancel(); 339 } 340 341 if let UDPNetwork::Muxed(ref udp_mux) = self.udp_network { 342 let (ufrag, _) = self.get_local_user_credentials().await; 343 udp_mux.remove_conn_by_ufrag(&ufrag).await; 344 } 345 346 //FIXME: deadlock here 347 self.internal.close().await 348 } 349 350 /// Returns the selected pair or nil if there is none 351 pub fn get_selected_candidate_pair(&self) -> Option<Arc<CandidatePair>> { 352 self.internal.agent_conn.get_selected_pair() 353 } 354 355 /// Sets the credentials of the remote agent. 356 pub async fn set_remote_credentials( 357 &self, 358 remote_ufrag: String, 359 remote_pwd: String, 360 ) -> Result<()> { 361 self.internal 362 .set_remote_credentials(remote_ufrag, remote_pwd) 363 .await 364 } 365 366 /// Restarts the ICE Agent with the provided ufrag/pwd 367 /// If no ufrag/pwd is provided the Agent will generate one itself. 368 /// 369 /// Restart must only be called when `GatheringState` is `GatheringStateComplete` 370 /// a user must then call `GatherCandidates` explicitly to start generating new ones. 371 pub async fn restart(&self, mut ufrag: String, mut pwd: String) -> Result<()> { 372 if ufrag.is_empty() { 373 ufrag = generate_ufrag(); 374 } 375 if pwd.is_empty() { 376 pwd = generate_pwd(); 377 } 378 379 if ufrag.len() * 8 < 24 { 380 return Err(Error::ErrLocalUfragInsufficientBits); 381 } 382 if pwd.len() * 8 < 128 { 383 return Err(Error::ErrLocalPwdInsufficientBits); 384 } 385 386 if GatheringState::from(self.gathering_state.load(Ordering::SeqCst)) 387 == GatheringState::Gathering 388 { 389 return Err(Error::ErrRestartWhenGathering); 390 } 391 self.gathering_state 392 .store(GatheringState::New as u8, Ordering::SeqCst); 393 394 { 395 let done_tx = self.internal.done_tx.lock().await; 396 if done_tx.is_none() { 397 return Err(Error::ErrClosed); 398 } 399 } 400 401 // Clear all agent needed to take back to fresh state 402 { 403 let mut ufrag_pwd = self.internal.ufrag_pwd.lock().await; 404 ufrag_pwd.local_ufrag = ufrag; 405 ufrag_pwd.local_pwd = pwd; 406 ufrag_pwd.remote_ufrag = String::new(); 407 ufrag_pwd.remote_pwd = String::new(); 408 } 409 { 410 let mut pending_binding_requests = self.internal.pending_binding_requests.lock().await; 411 *pending_binding_requests = vec![]; 412 } 413 414 { 415 let mut checklist = self.internal.agent_conn.checklist.lock().await; 416 *checklist = vec![]; 417 } 418 419 self.internal.set_selected_pair(None).await; 420 self.internal.delete_all_candidates().await; 421 self.internal.start().await; 422 423 // Restart is used by NewAgent. Accept/Connect should be used to move to checking 424 // for new Agents 425 if self.internal.connection_state.load(Ordering::SeqCst) != ConnectionState::New as u8 { 426 self.internal 427 .update_connection_state(ConnectionState::Checking) 428 .await; 429 } 430 431 Ok(()) 432 } 433 434 /// Initiates the trickle based gathering process. 435 pub fn gather_candidates(&self) -> Result<()> { 436 if self.gathering_state.load(Ordering::SeqCst) != GatheringState::New as u8 { 437 return Err(Error::ErrMultipleGatherAttempted); 438 } 439 440 if self.internal.on_candidate_hdlr.load().is_none() { 441 return Err(Error::ErrNoOnCandidateHandler); 442 } 443 444 if let Some(gather_candidate_cancel) = &self.gather_candidate_cancel { 445 gather_candidate_cancel(); // Cancel previous gathering routine 446 } 447 448 //TODO: a.gatherCandidateCancel = cancel 449 450 let params = GatherCandidatesInternalParams { 451 udp_network: self.udp_network.clone(), 452 candidate_types: self.candidate_types.clone(), 453 urls: self.urls.clone(), 454 network_types: self.network_types.clone(), 455 mdns_mode: self.mdns_mode, 456 mdns_name: self.mdns_name.clone(), 457 net: Arc::clone(&self.net), 458 interface_filter: self.interface_filter.clone(), 459 ip_filter: self.ip_filter.clone(), 460 ext_ip_mapper: Arc::clone(&self.ext_ip_mapper), 461 agent_internal: Arc::clone(&self.internal), 462 gathering_state: Arc::clone(&self.gathering_state), 463 chan_candidate_tx: Arc::clone(&self.internal.chan_candidate_tx), 464 }; 465 tokio::spawn(async move { 466 Self::gather_candidates_internal(params).await; 467 }); 468 469 Ok(()) 470 } 471 472 /// Returns a list of candidate pair stats. 473 pub async fn get_candidate_pairs_stats(&self) -> Vec<CandidatePairStats> { 474 self.internal.get_candidate_pairs_stats().await 475 } 476 477 /// Returns a list of local candidates stats. 478 pub async fn get_local_candidates_stats(&self) -> Vec<CandidateStats> { 479 self.internal.get_local_candidates_stats().await 480 } 481 482 /// Returns a list of remote candidates stats. 483 pub async fn get_remote_candidates_stats(&self) -> Vec<CandidateStats> { 484 self.internal.get_remote_candidates_stats().await 485 } 486 487 async fn resolve_and_add_multicast_candidate( 488 mdns_conn: Arc<DnsConn>, 489 c: Arc<dyn Candidate + Send + Sync>, 490 ) -> Result<Arc<dyn Candidate + Send + Sync>> { 491 //TODO: hook up _close_query_signal_tx to Agent or Candidate's Close signal? 492 let (_close_query_signal_tx, close_query_signal_rx) = mpsc::channel(1); 493 let src = match mdns_conn.query(&c.address(), close_query_signal_rx).await { 494 Ok((_, src)) => src, 495 Err(err) => { 496 log::warn!("Failed to discover mDNS candidate {}: {}", c.address(), err); 497 return Err(err.into()); 498 } 499 }; 500 501 c.set_ip(&src.ip())?; 502 503 Ok(c) 504 } 505 506 async fn close_multicast_conn(mdns_conn: &Option<Arc<DnsConn>>) { 507 if let Some(conn) = mdns_conn { 508 if let Err(err) = conn.close().await { 509 log::warn!("failed to close mDNS Conn: {}", err); 510 } 511 } 512 } 513 } 514