use std::net::IpAddr;
use std::time::Duration;
use util::vnet::net::*;
use super::*;
use crate::error::*;
use crate::mdns::*;
use crate::network_type::*;
use crate::udp_network::UDPNetwork;
use crate::url::*;
pub(crate) const DEFAULT_CHECK_INTERVAL: Duration = Duration::from_millis(200);
pub(crate) const DEFAULT_KEEPALIVE_INTERVAL: Duration = Duration::from_secs(2);
pub(crate) const DEFAULT_DISCONNECTED_TIMEOUT: Duration = Duration::from_secs(5);
pub(crate) const DEFAULT_FAILED_TIMEOUT: Duration = Duration::from_secs(25);
pub(crate) const DEFAULT_HOST_ACCEPTANCE_MIN_WAIT: Duration = Duration::from_secs(0);
pub(crate) const DEFAULT_SRFLX_ACCEPTANCE_MIN_WAIT: Duration = Duration::from_millis(500);
pub(crate) const DEFAULT_PRFLX_ACCEPTANCE_MIN_WAIT: Duration = Duration::from_millis(1000);
pub(crate) const DEFAULT_RELAY_ACCEPTANCE_MIN_WAIT: Duration = Duration::from_millis(2000);
pub(crate) const DEFAULT_MAX_BINDING_REQUESTS: u16 = 7;
pub(crate) const MAX_BUFFER_SIZE: usize = 1000 * 1000;
pub(crate) const MAX_BINDING_REQUEST_TIMEOUT: Duration = Duration::from_millis(4000);
pub(crate) fn default_candidate_types() -> Vec<CandidateType> {
vec![
CandidateType::Host,
CandidateType::ServerReflexive,
CandidateType::Relay,
]
}
pub type InterfaceFilterFn = Box<dyn (Fn(&str) -> bool) + Send + Sync>;
pub type IpFilterFn = Box<dyn (Fn(IpAddr) -> bool) + Send + Sync>;
#[derive(Default)]
pub struct AgentConfig {
pub urls: Vec<Url>,
pub udp_network: UDPNetwork,
pub local_ufrag: String,
pub local_pwd: String,
pub multicast_dns_mode: MulticastDnsMode,
pub multicast_dns_host_name: String,
pub multicast_dns_dest_addr: String,
pub disconnected_timeout: Option<Duration>,
pub failed_timeout: Option<Duration>,
pub keepalive_interval: Option<Duration>,
pub network_types: Vec<NetworkType>,
pub candidate_types: Vec<CandidateType>,
pub check_interval: Duration,
pub max_binding_requests: Option<u16>,
pub is_controlling: bool,
pub lite: bool,
pub nat_1to1_ip_candidate_type: CandidateType,
pub nat_1to1_ips: Vec<String>,
pub host_acceptance_min_wait: Option<Duration>,
pub srflx_acceptance_min_wait: Option<Duration>,
pub prflx_acceptance_min_wait: Option<Duration>,
pub relay_acceptance_min_wait: Option<Duration>,
pub net: Option<Arc<Net>>,
pub interface_filter: Arc<Option<InterfaceFilterFn>>,
pub ip_filter: Arc<Option<IpFilterFn>>,
pub insecure_skip_verify: bool,
pub include_loopback: bool,
}
impl AgentConfig {
pub(crate) fn init_with_defaults(&self, a: &mut AgentInternal) {
if let Some(max_binding_requests) = self.max_binding_requests {
a.max_binding_requests = max_binding_requests;
} else {
a.max_binding_requests = DEFAULT_MAX_BINDING_REQUESTS;
}
if let Some(host_acceptance_min_wait) = self.host_acceptance_min_wait {
a.host_acceptance_min_wait = host_acceptance_min_wait;
} else {
a.host_acceptance_min_wait = DEFAULT_HOST_ACCEPTANCE_MIN_WAIT;
}
if let Some(srflx_acceptance_min_wait) = self.srflx_acceptance_min_wait {
a.srflx_acceptance_min_wait = srflx_acceptance_min_wait;
} else {
a.srflx_acceptance_min_wait = DEFAULT_SRFLX_ACCEPTANCE_MIN_WAIT;
}
if let Some(prflx_acceptance_min_wait) = self.prflx_acceptance_min_wait {
a.prflx_acceptance_min_wait = prflx_acceptance_min_wait;
} else {
a.prflx_acceptance_min_wait = DEFAULT_PRFLX_ACCEPTANCE_MIN_WAIT;
}
if let Some(relay_acceptance_min_wait) = self.relay_acceptance_min_wait {
a.relay_acceptance_min_wait = relay_acceptance_min_wait;
} else {
a.relay_acceptance_min_wait = DEFAULT_RELAY_ACCEPTANCE_MIN_WAIT;
}
if let Some(disconnected_timeout) = self.disconnected_timeout {
a.disconnected_timeout = disconnected_timeout;
} else {
a.disconnected_timeout = DEFAULT_DISCONNECTED_TIMEOUT;
}
if let Some(failed_timeout) = self.failed_timeout {
a.failed_timeout = failed_timeout;
} else {
a.failed_timeout = DEFAULT_FAILED_TIMEOUT;
}
if let Some(keepalive_interval) = self.keepalive_interval {
a.keepalive_interval = keepalive_interval;
} else {
a.keepalive_interval = DEFAULT_KEEPALIVE_INTERVAL;
}
if self.check_interval == Duration::from_secs(0) {
a.check_interval = DEFAULT_CHECK_INTERVAL;
} else {
a.check_interval = self.check_interval;
}
}
pub(crate) fn init_ext_ip_mapping(
&self,
mdns_mode: MulticastDnsMode,
candidate_types: &[CandidateType],
) -> Result<Option<ExternalIpMapper>> {
if let Some(ext_ip_mapper) =
ExternalIpMapper::new(self.nat_1to1_ip_candidate_type, &self.nat_1to1_ips)?
{
if ext_ip_mapper.candidate_type == CandidateType::Host {
if mdns_mode == MulticastDnsMode::QueryAndGather {
return Err(Error::ErrMulticastDnsWithNat1to1IpMapping);
}
let mut candi_host_enabled = false;
for candi_type in candidate_types {
if *candi_type == CandidateType::Host {
candi_host_enabled = true;
break;
}
}
if !candi_host_enabled {
return Err(Error::ErrIneffectiveNat1to1IpMappingHost);
}
} else if ext_ip_mapper.candidate_type == CandidateType::ServerReflexive {
let mut candi_srflx_enabled = false;
for candi_type in candidate_types {
if *candi_type == CandidateType::ServerReflexive {
candi_srflx_enabled = true;
break;
}
}
if !candi_srflx_enabled {
return Err(Error::ErrIneffectiveNat1to1IpMappingSrflx);
}
}
Ok(Some(ext_ip_mapper))
} else {
Ok(None)
}
}
}