Small cleanups and tweaks to same_subnet code.
This commit is contained in:
parent
3bc0a03848
commit
e4baf164dd
|
@ -3,7 +3,7 @@
|
|||
use super::TorPath;
|
||||
use crate::{DirInfo, Error, Result, TargetPort};
|
||||
use rand::Rng;
|
||||
use tor_netdir::{CircuitConfig, NetDir, Relay, WeightRole};
|
||||
use tor_netdir::{NetDir, Relay, SubnetConfig, WeightRole};
|
||||
|
||||
/// Internal representation of PathBuilder.
|
||||
enum ExitPathBuilderInner<'a> {
|
||||
|
@ -60,19 +60,19 @@ impl<'a> ExitPathBuilder<'a> {
|
|||
DirInfo::Directory(d) => d,
|
||||
};
|
||||
// TODO: properly get circuit config
|
||||
let circuit_config = CircuitConfig::default();
|
||||
let subnet_config = SubnetConfig::default();
|
||||
let exit = self.pick_exit(rng, netdir)?;
|
||||
|
||||
let middle = netdir
|
||||
.pick_relay(rng, WeightRole::Middle, |r| {
|
||||
r.can_be_in_same_circuit(&exit, &circuit_config)
|
||||
relays_can_share_circuit(r, &exit, &subnet_config)
|
||||
})
|
||||
.ok_or_else(|| Error::NoRelays("No middle relay found".into()))?;
|
||||
|
||||
let entry = netdir
|
||||
.pick_relay(rng, WeightRole::Guard, |r| {
|
||||
r.can_be_in_same_circuit(&middle, &circuit_config)
|
||||
&& r.can_be_in_same_circuit(&exit, &circuit_config)
|
||||
relays_can_share_circuit(r, &middle, &subnet_config)
|
||||
&& relays_can_share_circuit(r, &exit, &subnet_config)
|
||||
})
|
||||
.ok_or_else(|| Error::NoRelays("No entry relay found".into()))?;
|
||||
|
||||
|
@ -80,6 +80,15 @@ impl<'a> ExitPathBuilder<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if both relays can appear together in the same circuit.
|
||||
fn relays_can_share_circuit(a: &Relay<'_>, b: &Relay<'_>, subnet_config: &SubnetConfig) -> bool {
|
||||
// XXX: features missing from original implementation:
|
||||
// - option NodeFamilySets
|
||||
// see: src/feature/nodelist/nodelist.c:nodes_in_same_family()
|
||||
|
||||
!a.in_same_family(b) && !a.in_same_subnet(b, subnet_config)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
@ -101,10 +110,10 @@ mod test {
|
|||
assert!(r1.ed_identity() != r3.ed_identity());
|
||||
assert!(r2.ed_identity() != r3.ed_identity());
|
||||
|
||||
let circuit_config = CircuitConfig::default();
|
||||
assert!(r1.can_be_in_same_circuit(r2, &circuit_config));
|
||||
assert!(r1.can_be_in_same_circuit(r3, &circuit_config));
|
||||
assert!(r2.can_be_in_same_circuit(r3, &circuit_config));
|
||||
let subnet_config = SubnetConfig::default();
|
||||
assert!(relays_can_share_circuit(r1, r2, &subnet_config));
|
||||
assert!(relays_can_share_circuit(r1, r3, &subnet_config));
|
||||
assert!(relays_can_share_circuit(r2, r3, &subnet_config));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -76,17 +76,20 @@ pub type Result<T> = std::result::Result<T, Error>;
|
|||
|
||||
use params::NetParameters;
|
||||
|
||||
/// The configuration for circuit creation.
|
||||
/// Configuration for determining when two relays have addresses "too close" in
|
||||
/// the network.
|
||||
///
|
||||
/// Used by [`Relay::in_same_subnet()`].
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CircuitConfig {
|
||||
pub struct SubnetConfig {
|
||||
/// Consider IPv4 nodes in the same /x to be the same family.
|
||||
subnets_family_v4: u8,
|
||||
/// Consider IPv6 nodes in the same /x to be the same family.
|
||||
subnets_family_v6: u8,
|
||||
}
|
||||
|
||||
impl Default for CircuitConfig {
|
||||
impl Default for SubnetConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
subnets_family_v4: 16,
|
||||
|
@ -511,19 +514,14 @@ impl<'a> Relay<'a> {
|
|||
.protovers()
|
||||
.supports_known_subver(ProtoKind::DirCache, 2)
|
||||
}
|
||||
/// Returns true if both relays can appear together in the same circuit.
|
||||
pub fn can_be_in_same_circuit<'b>(
|
||||
&self,
|
||||
other: &Relay<'b>,
|
||||
circuit_config: &CircuitConfig,
|
||||
) -> bool {
|
||||
// XXX: features missing from original implementation:
|
||||
// - option NodeFamilySets
|
||||
// see: src/feature/nodelist/nodelist.c:nodes_in_same_family()
|
||||
!self.in_same_family(other) && !self.same_subnet(other, circuit_config)
|
||||
}
|
||||
/// If two relays are on the same subnet.
|
||||
pub fn same_subnet<'b>(&self, other: &Relay<'b>, circuit_config: &CircuitConfig) -> bool {
|
||||
/// Return true if both relays are in the same subnet, as configured by
|
||||
/// `subnet_config`.
|
||||
///
|
||||
/// Two relays are considered to be in the same subnet if they
|
||||
/// have IPv4 addresses with the same `subnets_family_v4`-bit
|
||||
/// prefix, or if they have IPv6 addresses with the same
|
||||
/// `subnets_family_v6`-bit prefix.
|
||||
pub fn in_same_subnet<'b>(&self, other: &Relay<'b>, subnet_config: &SubnetConfig) -> bool {
|
||||
/// Do the two addresses share the same n leading bits?
|
||||
fn addrs_equal(a: &SocketAddr, b: &SocketAddr, v4_bits: u8, v6_bits: u8) -> bool {
|
||||
match (a.ip(), b.ip()) {
|
||||
|
@ -546,19 +544,16 @@ impl<'a> Relay<'a> {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
self.rs
|
||||
.orport_addrs()
|
||||
// TODO: get bit length from config
|
||||
.any(|addr| {
|
||||
other.rs.orport_addrs().any(|other| {
|
||||
addrs_equal(
|
||||
addr,
|
||||
other,
|
||||
circuit_config.subnets_family_v4,
|
||||
circuit_config.subnets_family_v6,
|
||||
)
|
||||
})
|
||||
self.rs.orport_addrs().any(|addr| {
|
||||
other.rs.orport_addrs().any(|other| {
|
||||
addrs_equal(
|
||||
addr,
|
||||
other,
|
||||
subnet_config.subnets_family_v4,
|
||||
subnet_config.subnets_family_v6,
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
/// Return true if both relays are in the same family.
|
||||
///
|
||||
|
@ -836,7 +831,7 @@ mod test {
|
|||
#[test]
|
||||
fn relay_funcs() {
|
||||
let (consensus, microdescs) = construct_network();
|
||||
let circuit_config = CircuitConfig::default();
|
||||
let subnet_config = SubnetConfig::default();
|
||||
let mut dir = PartialNetDir::new(consensus, None);
|
||||
for md in microdescs.into_iter() {
|
||||
let wanted = dir.add_microdesc(md.clone());
|
||||
|
@ -879,11 +874,11 @@ mod test {
|
|||
assert!(r2.in_same_family(&r2));
|
||||
assert!(r2.in_same_family(&r3));
|
||||
|
||||
assert!(r0.same_subnet(&r10, &circuit_config));
|
||||
assert!(r10.same_subnet(&r10, &circuit_config));
|
||||
assert!(r0.same_subnet(&r0, &circuit_config));
|
||||
assert!(r1.same_subnet(&r1, &circuit_config));
|
||||
assert!(!r1.same_subnet(&r2, &circuit_config));
|
||||
assert!(!r2.same_subnet(&r3, &circuit_config));
|
||||
assert!(r0.in_same_subnet(&r10, &subnet_config));
|
||||
assert!(r10.in_same_subnet(&r10, &subnet_config));
|
||||
assert!(r0.in_same_subnet(&r0, &subnet_config));
|
||||
assert!(r1.in_same_subnet(&r1, &subnet_config));
|
||||
assert!(!r1.in_same_subnet(&r2, &subnet_config));
|
||||
assert!(!r2.in_same_subnet(&r3, &subnet_config));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue