webrtc_ice/agent/
agent_config.rs

1use std::net::IpAddr;
2use std::time::Duration;
3
4use util::vnet::net::*;
5
6use super::*;
7use crate::error::*;
8use crate::mdns::*;
9use crate::network_type::*;
10use crate::udp_network::UDPNetwork;
11use crate::url::*;
12
13/// The interval at which the agent performs candidate checks in the connecting phase.
14pub(crate) const DEFAULT_CHECK_INTERVAL: Duration = Duration::from_millis(200);
15
16/// The interval used to keep candidates alive.
17pub(crate) const DEFAULT_KEEPALIVE_INTERVAL: Duration = Duration::from_secs(2);
18
19/// The default time till an Agent transitions disconnected.
20pub(crate) const DEFAULT_DISCONNECTED_TIMEOUT: Duration = Duration::from_secs(5);
21
22/// The default time till an Agent transitions to failed after disconnected.
23pub(crate) const DEFAULT_FAILED_TIMEOUT: Duration = Duration::from_secs(25);
24
25/// Wait time before nominating a host candidate.
26pub(crate) const DEFAULT_HOST_ACCEPTANCE_MIN_WAIT: Duration = Duration::from_secs(0);
27
28/// Wait time before nominating a srflx candidate.
29pub(crate) const DEFAULT_SRFLX_ACCEPTANCE_MIN_WAIT: Duration = Duration::from_millis(500);
30
31/// Wait time before nominating a prflx candidate.
32pub(crate) const DEFAULT_PRFLX_ACCEPTANCE_MIN_WAIT: Duration = Duration::from_millis(1000);
33
34/// Wait time before nominating a relay candidate.
35pub(crate) const DEFAULT_RELAY_ACCEPTANCE_MIN_WAIT: Duration = Duration::from_millis(2000);
36
37/// Max binding request before considering a pair failed.
38pub(crate) const DEFAULT_MAX_BINDING_REQUESTS: u16 = 7;
39
40/// The number of bytes that can be buffered before we start to error.
41pub(crate) const MAX_BUFFER_SIZE: usize = 1000 * 1000; // 1MB
42
43/// Wait time before binding requests can be deleted.
44pub(crate) const MAX_BINDING_REQUEST_TIMEOUT: Duration = Duration::from_millis(4000);
45
46pub(crate) fn default_candidate_types() -> Vec<CandidateType> {
47    vec![
48        CandidateType::Host,
49        CandidateType::ServerReflexive,
50        CandidateType::Relay,
51    ]
52}
53
54pub type InterfaceFilterFn = Box<dyn (Fn(&str) -> bool) + Send + Sync>;
55pub type IpFilterFn = Box<dyn (Fn(IpAddr) -> bool) + Send + Sync>;
56
57/// Collects the arguments to `ice::Agent` construction into a single structure, for
58/// future-proofness of the interface.
59#[derive(Default)]
60pub struct AgentConfig {
61    pub urls: Vec<Url>,
62
63    /// Controls how the UDP network stack works.
64    /// See [`UDPNetwork`]
65    pub udp_network: UDPNetwork,
66
67    /// It is used to perform connectivity checks. The values MUST be unguessable, with at least
68    /// 128 bits of random number generator output used to generate the password, and at least 24
69    /// bits of output to generate the username fragment.
70    pub local_ufrag: String,
71    /// It is used to perform connectivity checks. The values MUST be unguessable, with at least
72    /// 128 bits of random number generator output used to generate the password, and at least 24
73    /// bits of output to generate the username fragment.
74    pub local_pwd: String,
75
76    /// Controls mDNS behavior for the ICE agent.
77    pub multicast_dns_mode: MulticastDnsMode,
78
79    /// Controls the hostname for this agent. If none is specified a random one will be generated.
80    pub multicast_dns_host_name: String,
81
82    /// Control mDNS destination address
83    pub multicast_dns_dest_addr: String,
84
85    /// Defaults to 5 seconds when this property is nil.
86    /// If the duration is 0, the ICE Agent will never go to disconnected.
87    pub disconnected_timeout: Option<Duration>,
88
89    /// Defaults to 25 seconds when this property is nil.
90    /// If the duration is 0, we will never go to failed.
91    pub failed_timeout: Option<Duration>,
92
93    /// Determines how often should we send ICE keepalives (should be less then connectiontimeout
94    /// above) when this is nil, it defaults to 10 seconds.
95    /// A keepalive interval of 0 means we never send keepalive packets
96    pub keepalive_interval: Option<Duration>,
97
98    /// An optional configuration for disabling or enabling support for specific network types.
99    pub network_types: Vec<NetworkType>,
100
101    /// An optional configuration for disabling or enabling support for specific candidate types.
102    pub candidate_types: Vec<CandidateType>,
103
104    //LoggerFactory logging.LoggerFactory
105    /// Controls how often our internal task loop runs when in the connecting state.
106    /// Only useful for testing.
107    pub check_interval: Duration,
108
109    /// The max amount of binding requests the agent will send over a candidate pair for validation
110    /// or nomination, if after max_binding_requests the candidate is yet to answer a binding
111    /// request or a nomination we set the pair as failed.
112    pub max_binding_requests: Option<u16>,
113
114    pub is_controlling: bool,
115
116    /// lite agents do not perform connectivity check and only provide host candidates.
117    pub lite: bool,
118
119    /// It is used along with nat1to1ips to specify which candidate type the 1:1 NAT IP addresses
120    /// should be mapped to. If unspecified or CandidateTypeHost, nat1to1ips are used to replace
121    /// host candidate IPs. If CandidateTypeServerReflexive, it will insert a srflx candidate (as
122    /// if it was derived from a STUN server) with its port number being the one for the actual host
123    /// candidate.  Other values will result in an error.
124    pub nat_1to1_ip_candidate_type: CandidateType,
125
126    /// Contains a list of public IP addresses that are to be used as a host candidate or srflx
127    /// candidate. This is used typically for servers that are behind 1:1 D-NAT (e.g. AWS EC2
128    /// instances) and to eliminate the need of server reflexisive candidate gathering.
129    pub nat_1to1_ips: Vec<String>,
130
131    /// Specify a minimum wait time before selecting host candidates.
132    pub host_acceptance_min_wait: Option<Duration>,
133    /// Specify a minimum wait time before selecting srflx candidates.
134    pub srflx_acceptance_min_wait: Option<Duration>,
135    /// Specify a minimum wait time before selecting prflx candidates.
136    pub prflx_acceptance_min_wait: Option<Duration>,
137    /// Specify a minimum wait time before selecting relay candidates.
138    pub relay_acceptance_min_wait: Option<Duration>,
139
140    /// Net is the our abstracted network interface for internal development purpose only
141    /// (see (github.com/pion/transport/vnet)[github.com/pion/transport/vnet]).
142    pub net: Option<Arc<Net>>,
143
144    /// A function that you can use in order to whitelist or blacklist the interfaces which are
145    /// used to gather ICE candidates.
146    pub interface_filter: Arc<Option<InterfaceFilterFn>>,
147
148    /// A function that you can use in order to whitelist or blacklist
149    /// the ips which are used to gather ICE candidates.
150    pub ip_filter: Arc<Option<IpFilterFn>>,
151
152    /// Controls if self-signed certificates are accepted when connecting to TURN servers via TLS or
153    /// DTLS.
154    pub insecure_skip_verify: bool,
155
156    /// Include loopback addresses in the candidate list.
157    pub include_loopback: bool,
158}
159
160impl AgentConfig {
161    /// Populates an agent and falls back to defaults if fields are unset.
162    pub(crate) fn init_with_defaults(&self, a: &mut AgentInternal) {
163        if let Some(max_binding_requests) = self.max_binding_requests {
164            a.max_binding_requests = max_binding_requests;
165        } else {
166            a.max_binding_requests = DEFAULT_MAX_BINDING_REQUESTS;
167        }
168
169        if let Some(host_acceptance_min_wait) = self.host_acceptance_min_wait {
170            a.host_acceptance_min_wait = host_acceptance_min_wait;
171        } else {
172            a.host_acceptance_min_wait = DEFAULT_HOST_ACCEPTANCE_MIN_WAIT;
173        }
174
175        if let Some(srflx_acceptance_min_wait) = self.srflx_acceptance_min_wait {
176            a.srflx_acceptance_min_wait = srflx_acceptance_min_wait;
177        } else {
178            a.srflx_acceptance_min_wait = DEFAULT_SRFLX_ACCEPTANCE_MIN_WAIT;
179        }
180
181        if let Some(prflx_acceptance_min_wait) = self.prflx_acceptance_min_wait {
182            a.prflx_acceptance_min_wait = prflx_acceptance_min_wait;
183        } else {
184            a.prflx_acceptance_min_wait = DEFAULT_PRFLX_ACCEPTANCE_MIN_WAIT;
185        }
186
187        if let Some(relay_acceptance_min_wait) = self.relay_acceptance_min_wait {
188            a.relay_acceptance_min_wait = relay_acceptance_min_wait;
189        } else {
190            a.relay_acceptance_min_wait = DEFAULT_RELAY_ACCEPTANCE_MIN_WAIT;
191        }
192
193        if let Some(disconnected_timeout) = self.disconnected_timeout {
194            a.disconnected_timeout = disconnected_timeout;
195        } else {
196            a.disconnected_timeout = DEFAULT_DISCONNECTED_TIMEOUT;
197        }
198
199        if let Some(failed_timeout) = self.failed_timeout {
200            a.failed_timeout = failed_timeout;
201        } else {
202            a.failed_timeout = DEFAULT_FAILED_TIMEOUT;
203        }
204
205        if let Some(keepalive_interval) = self.keepalive_interval {
206            a.keepalive_interval = keepalive_interval;
207        } else {
208            a.keepalive_interval = DEFAULT_KEEPALIVE_INTERVAL;
209        }
210
211        if self.check_interval == Duration::from_secs(0) {
212            a.check_interval = DEFAULT_CHECK_INTERVAL;
213        } else {
214            a.check_interval = self.check_interval;
215        }
216    }
217
218    pub(crate) fn init_ext_ip_mapping(
219        &self,
220        mdns_mode: MulticastDnsMode,
221        candidate_types: &[CandidateType],
222    ) -> Result<Option<ExternalIpMapper>> {
223        if let Some(ext_ip_mapper) =
224            ExternalIpMapper::new(self.nat_1to1_ip_candidate_type, &self.nat_1to1_ips)?
225        {
226            if ext_ip_mapper.candidate_type == CandidateType::Host {
227                if mdns_mode == MulticastDnsMode::QueryAndGather {
228                    return Err(Error::ErrMulticastDnsWithNat1to1IpMapping);
229                }
230                let mut candi_host_enabled = false;
231                for candi_type in candidate_types {
232                    if *candi_type == CandidateType::Host {
233                        candi_host_enabled = true;
234                        break;
235                    }
236                }
237                if !candi_host_enabled {
238                    return Err(Error::ErrIneffectiveNat1to1IpMappingHost);
239                }
240            } else if ext_ip_mapper.candidate_type == CandidateType::ServerReflexive {
241                let mut candi_srflx_enabled = false;
242                for candi_type in candidate_types {
243                    if *candi_type == CandidateType::ServerReflexive {
244                        candi_srflx_enabled = true;
245                        break;
246                    }
247                }
248                if !candi_srflx_enabled {
249                    return Err(Error::ErrIneffectiveNat1to1IpMappingSrflx);
250                }
251            }
252
253            Ok(Some(ext_ip_mapper))
254        } else {
255            Ok(None)
256        }
257    }
258}