1 use super::*; 2 use crate::candidate::candidate_host::CandidateHostConfig; 3 use crate::candidate::candidate_peer_reflexive::CandidatePeerReflexiveConfig; 4 use crate::candidate::candidate_relay::CandidateRelayConfig; 5 use crate::candidate::candidate_server_reflexive::CandidateServerReflexiveConfig; 6 use crate::error::*; 7 use crate::util::*; 8 9 use async_trait::async_trait; 10 use crc::{Crc, CRC_32_ISCSI}; 11 use std::fmt; 12 use std::ops::Add; 13 use std::sync::atomic::{AtomicU16, AtomicU64, AtomicU8, Ordering}; 14 use std::sync::Arc; 15 use std::time::{Duration, SystemTime, UNIX_EPOCH}; 16 use tokio::sync::{broadcast, Mutex}; 17 18 #[derive(Default)] 19 pub struct CandidateBaseConfig { 20 pub candidate_id: String, 21 pub network: String, 22 pub address: String, 23 pub port: u16, 24 pub component: u16, 25 pub priority: u32, 26 pub foundation: String, 27 pub conn: Option<Arc<dyn util::Conn + Send + Sync>>, 28 pub initialized_ch: Option<broadcast::Receiver<()>>, 29 } 30 31 pub(crate) type OnClose = fn() -> Result<()>; 32 33 pub struct CandidateBase { 34 pub(crate) id: String, 35 pub(crate) network_type: AtomicU8, 36 pub(crate) candidate_type: CandidateType, 37 38 pub(crate) component: AtomicU16, 39 pub(crate) address: String, 40 pub(crate) port: u16, 41 pub(crate) related_address: Option<CandidateRelatedAddress>, 42 pub(crate) tcp_type: TcpType, 43 44 pub(crate) resolved_addr: Mutex<SocketAddr>, 45 46 pub(crate) last_sent: AtomicU64, 47 pub(crate) last_received: AtomicU64, 48 49 pub(crate) conn: Option<Arc<dyn util::Conn + Send + Sync>>, 50 pub(crate) closed_ch: Arc<Mutex<Option<broadcast::Sender<()>>>>, 51 52 pub(crate) foundation_override: String, 53 pub(crate) priority_override: u32, 54 55 //CandidateHost 56 pub(crate) network: String, 57 //CandidateRelay 58 pub(crate) relay_client: Option<Arc<turn::client::Client>>, 59 } 60 61 impl Default for CandidateBase { 62 fn default() -> Self { 63 Self { 64 id: String::new(), 65 network_type: AtomicU8::new(0), 66 candidate_type: CandidateType::default(), 67 68 component: AtomicU16::new(0), 69 address: String::new(), 70 port: 0, 71 related_address: None, 72 tcp_type: TcpType::default(), 73 74 resolved_addr: Mutex::new(SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 0)), 75 76 last_sent: AtomicU64::new(0), 77 last_received: AtomicU64::new(0), 78 79 conn: None, 80 closed_ch: Arc::new(Mutex::new(None)), 81 82 foundation_override: String::new(), 83 priority_override: 0, 84 network: String::new(), 85 relay_client: None, 86 } 87 } 88 } 89 90 // String makes the candidateBase printable 91 impl fmt::Display for CandidateBase { 92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 93 if let Some(related_address) = self.related_address() { 94 write!( 95 f, 96 "{} {} {}:{}{}", 97 self.network_type(), 98 self.candidate_type(), 99 self.address(), 100 self.port(), 101 related_address, 102 ) 103 } else { 104 write!( 105 f, 106 "{} {} {}:{}", 107 self.network_type(), 108 self.candidate_type(), 109 self.address(), 110 self.port(), 111 ) 112 } 113 } 114 } 115 116 #[async_trait] 117 impl Candidate for CandidateBase { 118 fn foundation(&self) -> String { 119 if !self.foundation_override.is_empty() { 120 return self.foundation_override.clone(); 121 } 122 123 let mut buf = vec![]; 124 buf.extend_from_slice(self.candidate_type().to_string().as_bytes()); 125 buf.extend_from_slice(self.address.as_bytes()); 126 buf.extend_from_slice(self.network_type().to_string().as_bytes()); 127 128 let checksum = Crc::<u32>::new(&CRC_32_ISCSI).checksum(&buf); 129 130 format!("{}", checksum) 131 } 132 133 /// Returns Candidate ID. 134 fn id(&self) -> String { 135 self.id.clone() 136 } 137 138 /// Returns candidate component. 139 fn component(&self) -> u16 { 140 self.component.load(Ordering::SeqCst) 141 } 142 143 fn set_component(&self, component: u16) { 144 self.component.store(component, Ordering::SeqCst); 145 } 146 147 /// Returns a time indicating the last time this candidate was received. 148 fn last_received(&self) -> SystemTime { 149 UNIX_EPOCH.add(Duration::from_nanos( 150 self.last_received.load(Ordering::SeqCst), 151 )) 152 } 153 154 /// Returns a time indicating the last time this candidate was sent. 155 fn last_sent(&self) -> SystemTime { 156 UNIX_EPOCH.add(Duration::from_nanos(self.last_sent.load(Ordering::SeqCst))) 157 } 158 159 /// Returns candidate NetworkType. 160 fn network_type(&self) -> NetworkType { 161 NetworkType::from(self.network_type.load(Ordering::SeqCst)) 162 } 163 164 /// Returns Candidate Address. 165 fn address(&self) -> String { 166 self.address.clone() 167 } 168 169 /// Returns Candidate Port. 170 fn port(&self) -> u16 { 171 self.port 172 } 173 174 /// Computes the priority for this ICE Candidate. 175 fn priority(&self) -> u32 { 176 if self.priority_override != 0 { 177 return self.priority_override; 178 } 179 180 // The local preference MUST be an integer from 0 (lowest preference) to 181 // 65535 (highest preference) inclusive. When there is only a single IP 182 // address, this value SHOULD be set to 65535. If there are multiple 183 // candidates for a particular component for a particular data stream 184 // that have the same type, the local preference MUST be unique for each 185 // one. 186 (1 << 24) * u32::from(self.candidate_type().preference()) 187 + (1 << 8) * u32::from(self.local_preference()) 188 + (256 - u32::from(self.component())) 189 } 190 191 /// Returns `Option<CandidateRelatedAddress>`. 192 fn related_address(&self) -> Option<CandidateRelatedAddress> { 193 self.related_address.as_ref().cloned() 194 } 195 196 /// Returns candidate type. 197 fn candidate_type(&self) -> CandidateType { 198 self.candidate_type 199 } 200 201 fn tcp_type(&self) -> TcpType { 202 self.tcp_type 203 } 204 205 /// Returns the string representation of the ICECandidate. 206 fn marshal(&self) -> String { 207 let mut val = format!( 208 "{} {} {} {} {} {} typ {}", 209 self.foundation(), 210 self.component(), 211 self.network_type().network_short(), 212 self.priority(), 213 self.address(), 214 self.port(), 215 self.candidate_type() 216 ); 217 218 if self.tcp_type != TcpType::Unspecified { 219 val += format!(" tcptype {}", self.tcp_type()).as_str(); 220 } 221 222 if let Some(related_address) = self.related_address() { 223 val += format!( 224 " raddr {} rport {}", 225 related_address.address, related_address.port, 226 ) 227 .as_str(); 228 } 229 230 val 231 } 232 233 async fn addr(&self) -> SocketAddr { 234 let resolved_addr = self.resolved_addr.lock().await; 235 *resolved_addr 236 } 237 238 /// Stops the recvLoop. 239 async fn close(&self) -> Result<()> { 240 { 241 let mut closed_ch = self.closed_ch.lock().await; 242 if closed_ch.is_none() { 243 return Err(Error::ErrClosed); 244 } 245 closed_ch.take(); 246 } 247 248 if let Some(relay_client) = &self.relay_client { 249 let _ = relay_client.close().await; 250 } 251 252 if let Some(conn) = &self.conn { 253 let _ = conn.close().await; 254 } 255 256 Ok(()) 257 } 258 259 fn seen(&self, outbound: bool) { 260 let d = SystemTime::now() 261 .duration_since(UNIX_EPOCH) 262 .unwrap_or_else(|_| Duration::from_secs(0)); 263 264 if outbound { 265 self.set_last_sent(d); 266 } else { 267 self.set_last_received(d); 268 } 269 } 270 271 async fn write_to(&self, raw: &[u8], dst: &(dyn Candidate + Send + Sync)) -> Result<usize> { 272 let n = if let Some(conn) = &self.conn { 273 let addr = dst.addr().await; 274 conn.send_to(raw, addr).await? 275 } else { 276 0 277 }; 278 self.seen(true); 279 Ok(n) 280 } 281 282 /// Used to compare two candidateBases. 283 fn equal(&self, other: &dyn Candidate) -> bool { 284 self.network_type() == other.network_type() 285 && self.candidate_type() == other.candidate_type() 286 && self.address() == other.address() 287 && self.port() == other.port() 288 && self.tcp_type() == other.tcp_type() 289 && self.related_address() == other.related_address() 290 } 291 292 async fn set_ip(&self, ip: &IpAddr) -> Result<()> { 293 let network_type = determine_network_type(&self.network, ip)?; 294 295 self.network_type 296 .store(network_type as u8, Ordering::SeqCst); 297 298 let mut resolved_addr = self.resolved_addr.lock().await; 299 *resolved_addr = create_addr(network_type, *ip, self.port); 300 301 Ok(()) 302 } 303 304 fn get_conn(&self) -> Option<&Arc<dyn util::Conn + Send + Sync>> { 305 self.conn.as_ref() 306 } 307 308 fn get_closed_ch(&self) -> Arc<Mutex<Option<broadcast::Sender<()>>>> { 309 self.closed_ch.clone() 310 } 311 } 312 313 impl CandidateBase { 314 pub fn set_last_received(&self, d: Duration) { 315 #[allow(clippy::cast_possible_truncation)] 316 self.last_received 317 .store(d.as_nanos() as u64, Ordering::SeqCst); 318 } 319 320 pub fn set_last_sent(&self, d: Duration) { 321 #[allow(clippy::cast_possible_truncation)] 322 self.last_sent.store(d.as_nanos() as u64, Ordering::SeqCst); 323 } 324 325 /// Returns the local preference for this candidate. 326 pub fn local_preference(&self) -> u16 { 327 if self.network_type().is_tcp() { 328 // RFC 6544, section 4.2 329 // 330 // In Section 4.1.2.1 of [RFC5245], a recommended formula for UDP ICE 331 // candidate prioritization is defined. For TCP candidates, the same 332 // formula and candidate type preferences SHOULD be used, and the 333 // RECOMMENDED type preferences for the new candidate types defined in 334 // this document (see Section 5) are 105 for NAT-assisted candidates and 335 // 75 for UDP-tunneled candidates. 336 // 337 // (...) 338 // 339 // With TCP candidates, the local preference part of the recommended 340 // priority formula is updated to also include the directionality 341 // (active, passive, or simultaneous-open) of the TCP connection. The 342 // RECOMMENDED local preference is then defined as: 343 // 344 // local preference = (2^13) * direction-pref + other-pref 345 // 346 // The direction-pref MUST be between 0 and 7 (both inclusive), with 7 347 // being the most preferred. The other-pref MUST be between 0 and 8191 348 // (both inclusive), with 8191 being the most preferred. It is 349 // RECOMMENDED that the host, UDP-tunneled, and relayed TCP candidates 350 // have the direction-pref assigned as follows: 6 for active, 4 for 351 // passive, and 2 for S-O. For the NAT-assisted and server reflexive 352 // candidates, the RECOMMENDED values are: 6 for S-O, 4 for active, and 353 // 2 for passive. 354 // 355 // (...) 356 // 357 // If any two candidates have the same type-preference and direction- 358 // pref, they MUST have a unique other-pref. With this specification, 359 // this usually only happens with multi-homed hosts, in which case 360 // other-pref is the preference for the particular IP address from which 361 // the candidate was obtained. When there is only a single IP address, 362 // this value SHOULD be set to the maximum allowed value (8191). 363 let other_pref: u16 = 8191; 364 365 let direction_pref: u16 = match self.candidate_type() { 366 CandidateType::Host | CandidateType::Relay => match self.tcp_type() { 367 TcpType::Active => 6, 368 TcpType::Passive => 4, 369 TcpType::SimultaneousOpen => 2, 370 TcpType::Unspecified => 0, 371 }, 372 CandidateType::PeerReflexive | CandidateType::ServerReflexive => { 373 match self.tcp_type() { 374 TcpType::SimultaneousOpen => 6, 375 TcpType::Active => 4, 376 TcpType::Passive => 2, 377 TcpType::Unspecified => 0, 378 } 379 } 380 CandidateType::Unspecified => 0, 381 }; 382 383 (1 << 13) * direction_pref + other_pref 384 } else { 385 DEFAULT_LOCAL_PREFERENCE 386 } 387 } 388 } 389 390 /// Creates a Candidate from its string representation. 391 pub async fn unmarshal_candidate(raw: &str) -> Result<impl Candidate> { 392 let split: Vec<&str> = raw.split_whitespace().collect(); 393 if split.len() < 8 { 394 return Err(Error::Other(format!( 395 "{:?} ({})", 396 Error::ErrAttributeTooShortIceCandidate, 397 split.len() 398 ))); 399 } 400 401 // Foundation 402 let foundation = split[0].to_owned(); 403 404 // Component 405 let component: u16 = split[1].parse()?; 406 407 // Network 408 let network = split[2].to_owned(); 409 410 // Priority 411 let priority: u32 = split[3].parse()?; 412 413 // Address 414 let address = split[4].to_owned(); 415 416 // Port 417 let port: u16 = split[5].parse()?; 418 419 let typ = split[7]; 420 421 let mut rel_addr = String::new(); 422 let mut rel_port = 0; 423 let mut tcp_type = TcpType::Unspecified; 424 425 if split.len() > 8 { 426 let split2 = &split[8..]; 427 428 if split2[0] == "raddr" { 429 if split2.len() < 4 { 430 return Err(Error::Other(format!( 431 "{:?}: incorrect length", 432 Error::ErrParseRelatedAddr 433 ))); 434 } 435 436 // RelatedAddress 437 rel_addr = split2[1].to_owned(); 438 439 // RelatedPort 440 rel_port = split2[3].parse()?; 441 } else if split2[0] == "tcptype" { 442 if split2.len() < 2 { 443 return Err(Error::Other(format!( 444 "{:?}: incorrect length", 445 Error::ErrParseType 446 ))); 447 } 448 449 tcp_type = TcpType::from(split2[1]); 450 } 451 } 452 453 match typ { 454 "host" => { 455 let config = CandidateHostConfig { 456 base_config: CandidateBaseConfig { 457 network, 458 address, 459 port, 460 component, 461 priority, 462 foundation, 463 ..CandidateBaseConfig::default() 464 }, 465 tcp_type, 466 }; 467 config.new_candidate_host().await 468 } 469 "srflx" => { 470 let config = CandidateServerReflexiveConfig { 471 base_config: CandidateBaseConfig { 472 network, 473 address, 474 port, 475 component, 476 priority, 477 foundation, 478 ..CandidateBaseConfig::default() 479 }, 480 rel_addr, 481 rel_port, 482 }; 483 config.new_candidate_server_reflexive().await 484 } 485 "prflx" => { 486 let config = CandidatePeerReflexiveConfig { 487 base_config: CandidateBaseConfig { 488 network, 489 address, 490 port, 491 component, 492 priority, 493 foundation, 494 ..CandidateBaseConfig::default() 495 }, 496 rel_addr, 497 rel_port, 498 }; 499 500 config.new_candidate_peer_reflexive().await 501 } 502 "relay" => { 503 let config = CandidateRelayConfig { 504 base_config: CandidateBaseConfig { 505 network, 506 address, 507 port, 508 component, 509 priority, 510 foundation, 511 ..CandidateBaseConfig::default() 512 }, 513 rel_addr, 514 rel_port, 515 ..CandidateRelayConfig::default() 516 }; 517 config.new_candidate_relay().await 518 } 519 _ => Err(Error::Other(format!( 520 "{:?} ({})", 521 Error::ErrUnknownCandidateType, 522 typ 523 ))), 524 } 525 } 526