1 #[cfg(test)] 2 mod candidate_pair_test; 3 #[cfg(test)] 4 mod candidate_relay_test; 5 #[cfg(test)] 6 mod candidate_server_reflexive_test; 7 #[cfg(test)] 8 mod candidate_test; 9 10 pub mod candidate_base; 11 pub mod candidate_host; 12 pub mod candidate_peer_reflexive; 13 pub mod candidate_relay; 14 pub mod candidate_server_reflexive; 15 16 use crate::error::Result; 17 use crate::network_type::*; 18 use crate::tcp_type::*; 19 use candidate_base::*; 20 21 use async_trait::async_trait; 22 use serde::Serialize; 23 use std::fmt; 24 use std::net::{IpAddr, SocketAddr}; 25 use std::sync::atomic::{AtomicBool, AtomicU16, AtomicU8, Ordering}; 26 use std::sync::Arc; 27 use std::time::SystemTime; 28 use tokio::sync::{broadcast, Mutex}; 29 30 pub(crate) const RECEIVE_MTU: usize = 8192; 31 pub(crate) const DEFAULT_LOCAL_PREFERENCE: u16 = 65535; 32 33 /// Indicates that the candidate is used for RTP. 34 pub(crate) const COMPONENT_RTP: u16 = 1; 35 /// Indicates that the candidate is used for RTCP. 36 pub(crate) const COMPONENT_RTCP: u16 = 0; 37 38 /// Candidate represents an ICE candidate 39 #[async_trait] 40 pub trait Candidate: fmt::Display { 41 /// An arbitrary string used in the freezing algorithm to 42 /// group similar candidates. It is the same for two candidates that 43 /// have the same type, base IP address, protocol (UDP, TCP, etc.), 44 /// and STUN or TURN server. 45 fn foundation(&self) -> String; 46 47 /// A unique identifier for just this candidate 48 /// Unlike the foundation this is different for each candidate. 49 fn id(&self) -> String; 50 51 /// A component is a piece of a data stream. 52 /// An example is one for RTP, and one for RTCP 53 fn component(&self) -> u16; 54 fn set_component(&self, c: u16); 55 56 /// The last time this candidate received traffic 57 fn last_received(&self) -> SystemTime; 58 59 /// The last time this candidate sent traffic 60 fn last_sent(&self) -> SystemTime; 61 62 fn network_type(&self) -> NetworkType; 63 fn address(&self) -> String; 64 fn port(&self) -> u16; 65 66 fn priority(&self) -> u32; 67 68 /// A transport address related to candidate, 69 /// which is useful for diagnostics and other purposes. 70 fn related_address(&self) -> Option<CandidateRelatedAddress>; 71 72 fn candidate_type(&self) -> CandidateType; 73 fn tcp_type(&self) -> TcpType; 74 75 fn marshal(&self) -> String; 76 77 fn addr(&self) -> SocketAddr; 78 79 async fn close(&self) -> Result<()>; 80 fn seen(&self, outbound: bool); 81 82 async fn write_to(&self, raw: &[u8], dst: &(dyn Candidate + Send + Sync)) -> Result<usize>; 83 fn equal(&self, other: &dyn Candidate) -> bool; 84 fn set_ip(&self, ip: &IpAddr) -> Result<()>; 85 fn get_conn(&self) -> Option<&Arc<dyn util::Conn + Send + Sync>>; 86 fn get_closed_ch(&self) -> Arc<Mutex<Option<broadcast::Sender<()>>>>; 87 } 88 89 /// Represents the type of candidate `CandidateType` enum. 90 #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] 91 pub enum CandidateType { 92 #[serde(rename = "unspecified")] 93 Unspecified, 94 #[serde(rename = "host")] 95 Host, 96 #[serde(rename = "srflx")] 97 ServerReflexive, 98 #[serde(rename = "prflx")] 99 PeerReflexive, 100 #[serde(rename = "relay")] 101 Relay, 102 } 103 104 // String makes CandidateType printable 105 impl fmt::Display for CandidateType { 106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 107 let s = match *self { 108 CandidateType::Host => "host", 109 CandidateType::ServerReflexive => "srflx", 110 CandidateType::PeerReflexive => "prflx", 111 CandidateType::Relay => "relay", 112 CandidateType::Unspecified => "Unknown candidate type", 113 }; 114 write!(f, "{}", s) 115 } 116 } 117 118 impl Default for CandidateType { 119 fn default() -> Self { 120 Self::Unspecified 121 } 122 } 123 124 impl CandidateType { 125 /// Returns the preference weight of a `CandidateType`. 126 /// 127 /// 4.1.2.2. Guidelines for Choosing Type and Local Preferences 128 /// The RECOMMENDED values are 126 for host candidates, 100 129 /// for server reflexive candidates, 110 for peer reflexive candidates, 130 /// and 0 for relayed candidates. 131 #[must_use] 132 pub const fn preference(self) -> u16 { 133 match self { 134 Self::Host => 126, 135 Self::PeerReflexive => 110, 136 Self::ServerReflexive => 100, 137 Self::Relay | CandidateType::Unspecified => 0, 138 } 139 } 140 } 141 142 pub(crate) fn contains_candidate_type( 143 candidate_type: CandidateType, 144 candidate_type_list: &[CandidateType], 145 ) -> bool { 146 if candidate_type_list.is_empty() { 147 return false; 148 } 149 for ct in candidate_type_list { 150 if *ct == candidate_type { 151 return true; 152 } 153 } 154 false 155 } 156 157 /// Convey transport addresses related to the candidate, useful for diagnostics and other purposes. 158 #[derive(PartialEq, Eq, Debug, Clone)] 159 pub struct CandidateRelatedAddress { 160 pub address: String, 161 pub port: u16, 162 } 163 164 // String makes CandidateRelatedAddress printable 165 impl fmt::Display for CandidateRelatedAddress { 166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 167 write!(f, " related {}:{}", self.address, self.port) 168 } 169 } 170 171 /// Represent the ICE candidate pair state. 172 #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] 173 pub enum CandidatePairState { 174 #[serde(rename = "unspecified")] 175 Unspecified = 0, 176 177 /// Means a check has not been performed for this pair. 178 #[serde(rename = "waiting")] 179 Waiting = 1, 180 181 /// Means a check has been sent for this pair, but the transaction is in progress. 182 #[serde(rename = "in-progress")] 183 InProgress = 2, 184 185 /// Means a check for this pair was already done and failed, either never producing any response 186 /// or producing an unrecoverable failure response. 187 #[serde(rename = "failed")] 188 Failed = 3, 189 190 /// Means a check for this pair was already done and produced a successful result. 191 #[serde(rename = "succeeded")] 192 Succeeded = 4, 193 } 194 195 impl From<u8> for CandidatePairState { 196 fn from(v: u8) -> Self { 197 match v { 198 1 => Self::Waiting, 199 2 => Self::InProgress, 200 3 => Self::Failed, 201 4 => Self::Succeeded, 202 _ => Self::Unspecified, 203 } 204 } 205 } 206 207 impl Default for CandidatePairState { 208 fn default() -> Self { 209 Self::Unspecified 210 } 211 } 212 213 impl fmt::Display for CandidatePairState { 214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 215 let s = match *self { 216 Self::Waiting => "waiting", 217 Self::InProgress => "in-progress", 218 Self::Failed => "failed", 219 Self::Succeeded => "succeeded", 220 Self::Unspecified => "unspecified", 221 }; 222 223 write!(f, "{}", s) 224 } 225 } 226 227 /// Represents a combination of a local and remote candidate. 228 pub struct CandidatePair { 229 pub(crate) ice_role_controlling: AtomicBool, 230 pub remote: Arc<dyn Candidate + Send + Sync>, 231 pub local: Arc<dyn Candidate + Send + Sync>, 232 pub(crate) binding_request_count: AtomicU16, 233 pub(crate) state: AtomicU8, // convert it to CandidatePairState, 234 pub(crate) nominated: AtomicBool, 235 } 236 237 impl Default for CandidatePair { 238 fn default() -> Self { 239 Self { 240 ice_role_controlling: AtomicBool::new(false), 241 remote: Arc::new(CandidateBase::default()), 242 local: Arc::new(CandidateBase::default()), 243 state: AtomicU8::new(CandidatePairState::Waiting as u8), 244 binding_request_count: AtomicU16::new(0), 245 nominated: AtomicBool::new(false), 246 } 247 } 248 } 249 250 impl fmt::Debug for CandidatePair { 251 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 252 write!( 253 f, 254 "prio {} (local, prio {}) {} <-> {} (remote, prio {})", 255 self.priority(), 256 self.local.priority(), 257 self.local, 258 self.remote, 259 self.remote.priority() 260 ) 261 } 262 } 263 264 impl fmt::Display for CandidatePair { 265 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 266 write!( 267 f, 268 "prio {} (local, prio {}) {} <-> {} (remote, prio {})", 269 self.priority(), 270 self.local.priority(), 271 self.local, 272 self.remote, 273 self.remote.priority() 274 ) 275 } 276 } 277 278 impl PartialEq for CandidatePair { 279 fn eq(&self, other: &Self) -> bool { 280 self.local.equal(&*other.local) && self.remote.equal(&*other.remote) 281 } 282 } 283 284 impl CandidatePair { 285 #[must_use] 286 pub fn new( 287 local: Arc<dyn Candidate + Send + Sync>, 288 remote: Arc<dyn Candidate + Send + Sync>, 289 controlling: bool, 290 ) -> Self { 291 Self { 292 ice_role_controlling: AtomicBool::new(controlling), 293 remote, 294 local, 295 state: AtomicU8::new(CandidatePairState::Waiting as u8), 296 binding_request_count: AtomicU16::new(0), 297 nominated: AtomicBool::new(false), 298 } 299 } 300 301 /// RFC 5245 - 5.7.2. Computing Pair Priority and Ordering Pairs 302 /// Let G be the priority for the candidate provided by the controlling 303 /// agent. Let D be the priority for the candidate provided by the 304 /// controlled agent. 305 /// pair priority = 2^32*MIN(G,D) + 2*MAX(G,D) + (G>D?1:0) 306 pub fn priority(&self) -> u64 { 307 let (g, d) = if self.ice_role_controlling.load(Ordering::SeqCst) { 308 (self.local.priority(), self.remote.priority()) 309 } else { 310 (self.remote.priority(), self.local.priority()) 311 }; 312 313 // 1<<32 overflows uint32; and if both g && d are 314 // maxUint32, this result would overflow uint64 315 ((1 << 32_u64) - 1) * u64::from(std::cmp::min(g, d)) 316 + 2 * u64::from(std::cmp::max(g, d)) 317 + u64::from(g > d) 318 } 319 320 pub async fn write(&self, b: &[u8]) -> Result<usize> { 321 self.local.write_to(b, &*self.remote).await 322 } 323 } 324