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