xref: /webrtc/ice/src/candidate/mod.rs (revision 5d8fe953)
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.
foundation(&self) -> String45     fn foundation(&self) -> String;
46 
47     /// A unique identifier for just this candidate
48     /// Unlike the foundation this is different for each candidate.
id(&self) -> String49     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
component(&self) -> u1653     fn component(&self) -> u16;
set_component(&self, c: u16)54     fn set_component(&self, c: u16);
55 
56     /// The last time this candidate received traffic
last_received(&self) -> SystemTime57     fn last_received(&self) -> SystemTime;
58 
59     /// The last time this candidate sent traffic
last_sent(&self) -> SystemTime60     fn last_sent(&self) -> SystemTime;
61 
network_type(&self) -> NetworkType62     fn network_type(&self) -> NetworkType;
address(&self) -> String63     fn address(&self) -> String;
port(&self) -> u1664     fn port(&self) -> u16;
65 
priority(&self) -> u3266     fn priority(&self) -> u32;
67 
68     /// A transport address related to candidate,
69     /// which is useful for diagnostics and other purposes.
related_address(&self) -> Option<CandidateRelatedAddress>70     fn related_address(&self) -> Option<CandidateRelatedAddress>;
71 
candidate_type(&self) -> CandidateType72     fn candidate_type(&self) -> CandidateType;
tcp_type(&self) -> TcpType73     fn tcp_type(&self) -> TcpType;
74 
marshal(&self) -> String75     fn marshal(&self) -> String;
76 
addr(&self) -> SocketAddr77     fn addr(&self) -> SocketAddr;
78 
close(&self) -> Result<()>79     async fn close(&self) -> Result<()>;
seen(&self, outbound: bool)80     fn seen(&self, outbound: bool);
81 
write_to(&self, raw: &[u8], dst: &(dyn Candidate + Send + Sync)) -> Result<usize>82     async fn write_to(&self, raw: &[u8], dst: &(dyn Candidate + Send + Sync)) -> Result<usize>;
equal(&self, other: &dyn Candidate) -> bool83     fn equal(&self, other: &dyn Candidate) -> bool;
set_ip(&self, ip: &IpAddr) -> Result<()>84     fn set_ip(&self, ip: &IpAddr) -> Result<()>;
get_conn(&self) -> Option<&Arc<dyn util::Conn + Send + Sync>>85     fn get_conn(&self) -> Option<&Arc<dyn util::Conn + Send + Sync>>;
get_closed_ch(&self) -> Arc<Mutex<Option<broadcast::Sender<()>>>>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 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result106     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 {
default() -> Self119     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]
preference(self) -> u16132     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 
contains_candidate_type( candidate_type: CandidateType, candidate_type_list: &[CandidateType], ) -> bool142 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 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result166     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 {
from(v: u8) -> Self196     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 {
default() -> Self208     fn default() -> Self {
209         Self::Unspecified
210     }
211 }
212 
213 impl fmt::Display for CandidatePairState {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result214     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 {
default() -> Self238     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 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result251     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 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result265     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 {
eq(&self, other: &Self) -> bool279     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]
new( local: Arc<dyn Candidate + Send + Sync>, remote: Arc<dyn Candidate + Send + Sync>, controlling: bool, ) -> Self286     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)
priority(&self) -> u64306     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 
write(&self, b: &[u8]) -> Result<usize>320     pub async fn write(&self, b: &[u8]) -> Result<usize> {
321         self.local.write_to(b, &*self.remote).await
322     }
323 }
324