GuardMgr: Add a new filter type based on reachable addresses.
This commit is contained in:
parent
801b6bec5f
commit
9c4f31edc1
|
@ -39,6 +39,7 @@ tor-error = { path = "../tor-error", version = "0.3.1" }
|
|||
tor-linkspec = { path = "../tor-linkspec", version = "0.3.0" }
|
||||
tor-llcrypto = { path = "../tor-llcrypto", version = "0.3.0" }
|
||||
tor-netdir = { path = "../tor-netdir", version = "0.3.0" }
|
||||
tor-netdoc = { path = "../tor-netdoc", version = "0.4.0" } # for address pattern
|
||||
tor-persist = { path = "../tor-persist", version = "0.4.0" }
|
||||
tor-proto = { path = "../tor-proto", version = "0.3.1" }
|
||||
tor-rtcompat = { path = "../tor-rtcompat", version = "0.4.0" }
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
//! Implement GuardFilter and related types.
|
||||
|
||||
use tor_linkspec::ChanTarget;
|
||||
// TODO(nickm): Conceivably, this type should be exposed from a lower-level crate than
|
||||
// tor-netdoc.
|
||||
use tor_netdoc::types::policy::AddrPortPattern;
|
||||
|
||||
/// An object specifying which relays are eligible to be guards.
|
||||
///
|
||||
|
@ -20,12 +23,21 @@ pub struct GuardFilter {
|
|||
/// A list of filters to apply to guard or fallback selection. Each filter
|
||||
/// restricts which guards may be used, and possibly how those guards may be
|
||||
/// contacted.
|
||||
///
|
||||
/// This list of filters has "and" semantics: a relay is permitted by this
|
||||
/// filter if ALL patterns in this list permit that first hop.
|
||||
filters: Vec<SingleFilter>,
|
||||
}
|
||||
|
||||
/// A single restriction places upon usable guards.
|
||||
#[derive(Debug, Clone)]
|
||||
enum SingleFilter {
|
||||
/// A set of allowable addresses that we are willing to try to connect to.
|
||||
///
|
||||
/// This list of patterns has "or" semantics: a guard is permitted by this filter
|
||||
/// if ANY pattern in this list permits one of the guard's addresses.
|
||||
ReachableAddrs(Vec<AddrPortPattern>),
|
||||
|
||||
/// Testing only: checks whether the first byte of the rsa key is 0 modulo 4.
|
||||
///
|
||||
/// TODO: remove this once real filters are implemented.
|
||||
|
@ -41,6 +53,13 @@ impl GuardFilter {
|
|||
GuardFilter::default()
|
||||
}
|
||||
|
||||
/// Restrict this filter to only permit connections to an address permitted
|
||||
/// by one of the patterns in `addrs`.
|
||||
pub fn push_reachable_addresses(&mut self, addrs: impl IntoIterator<Item = AddrPortPattern>) {
|
||||
self.filters
|
||||
.push(SingleFilter::ReachableAddrs(addrs.into_iter().collect()));
|
||||
}
|
||||
|
||||
/// Return true if this filter permits the provided `target`.
|
||||
pub(crate) fn permits<C: ChanTarget>(&self, target: &C) -> bool {
|
||||
self.filters.iter().all(|filt| filt.permits(target))
|
||||
|
@ -64,16 +83,12 @@ impl GuardFilter {
|
|||
impl SingleFilter {
|
||||
/// Return true if this filter permits the provided target.
|
||||
fn permits<C: ChanTarget>(&self, target: &C) -> bool {
|
||||
// TODO: This is ugly, but the whole function will get rewritten once we
|
||||
// have a real filter.
|
||||
#[cfg(test)]
|
||||
match self {
|
||||
SingleFilter::ReachableAddrs(patterns) => patterns
|
||||
.iter()
|
||||
.any(|pat| target.addrs().iter().any(|addr| pat.matches_sockaddr(addr))),
|
||||
#[cfg(test)]
|
||||
SingleFilter::TestingLimitKeys => target.rsa_identity().as_bytes()[0] & 3 == 0,
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
let _ = target;
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue