use std::sync::Arc;
use tor_linkspec::HasRelayIds;
use tor_netdoc::{doc::netstatus, types::policy::PortPolicy};
use crate::{FamilyRules, Relay, SubnetConfig};
#[derive(Clone)]
pub struct RelayDetails<'a>(pub(crate) &'a super::Relay<'a>);
impl<'a> RelayDetails<'a> {
pub fn supports_exit_port_ipv4(&self, port: u16) -> bool {
self.ipv4_policy().allows_port(port)
}
pub fn supports_exit_port_ipv6(&self, port: u16) -> bool {
self.ipv6_policy().allows_port(port)
}
pub fn is_dir_cache(&self) -> bool {
rs_is_dir_cache(self.0.rs)
}
pub fn is_flagged_fast(&self) -> bool {
self.0.rs.is_flagged_fast()
}
pub fn is_flagged_exit(&self) -> bool {
self.0.rs.is_flagged_exit()
}
pub fn is_flagged_stable(&self) -> bool {
self.0.rs.is_flagged_stable()
}
pub fn is_hs_intro_point(&self) -> bool {
self.is_flagged_fast()
&& self.0.rs.is_flagged_stable()
&& !self.0.rs.is_flagged_middle_only()
}
pub fn is_hs_rend_point(&self) -> bool {
self.is_flagged_fast()
&& self.0.rs.is_flagged_stable()
&& !self.0.rs.is_flagged_middle_only()
}
pub fn is_suitable_as_guard(&self) -> bool {
self.0.rs.is_flagged_guard() && self.is_flagged_fast() && self.is_flagged_stable()
}
pub fn in_same_subnet(&self, other: &Relay<'_>, subnet_config: &SubnetConfig) -> bool {
subnet_config.any_addrs_in_same_subnet(self.0, other)
}
pub fn in_same_family(&self, other: &Relay<'_>, family_rules: FamilyRules) -> bool {
#![allow(clippy::collapsible_if)] if self.0.same_relay_ids(other) {
return true;
}
if family_rules.use_family_lists {
if self.0.md.family().contains(other.rsa_id())
&& other.md.family().contains(self.0.rsa_id())
{
return true;
}
}
if family_rules.use_family_ids {
let my_ids = self.0.md.family_ids();
let their_ids = other.md.family_ids();
if my_ids.iter().any(|my_id| their_ids.contains(my_id)) {
return true;
}
}
false
}
pub fn policies_allow_some_port(&self) -> bool {
if self.0.rs.is_flagged_bad_exit() {
return false;
}
self.0.md.ipv4_policy().allows_some_port() || self.0.md.ipv6_policy().allows_some_port()
}
pub fn ipv4_policy(&self) -> Arc<PortPolicy> {
if !self.0.rs.is_flagged_bad_exit() {
Arc::clone(self.0.md.ipv4_policy())
} else {
Arc::new(PortPolicy::new_reject_all())
}
}
pub fn ipv6_policy(&self) -> Arc<PortPolicy> {
if !self.0.rs.is_flagged_bad_exit() {
Arc::clone(self.0.md.ipv6_policy())
} else {
Arc::new(PortPolicy::new_reject_all())
}
}
pub fn ipv4_declared_policy(&self) -> &Arc<PortPolicy> {
self.0.md.ipv4_policy()
}
pub fn ipv6_declared_policy(&self) -> &Arc<PortPolicy> {
self.0.md.ipv6_policy()
}
}
#[derive(Debug, Clone)]
pub struct UncheckedRelayDetails<'a>(pub(crate) &'a super::UncheckedRelay<'a>);
impl<'a> UncheckedRelayDetails<'a> {
pub fn is_suitable_as_guard(&self) -> bool {
self.0.rs.is_flagged_guard() && self.0.rs.is_flagged_fast() && self.0.rs.is_flagged_stable()
}
pub fn is_dir_cache(&self) -> bool {
rs_is_dir_cache(self.0.rs)
}
}
fn rs_is_dir_cache(rs: &netstatus::MdRouterStatus) -> bool {
use tor_protover::named::DIRCACHE_CONSDIFF;
rs.is_flagged_v2dir() && rs.protovers().supports_named_subver(DIRCACHE_CONSDIFF)
}