Guardmgr: Change the GuardFilter API.
The guard filter is now a set of restrictions that can be placed on allowable guards.
This commit is contained in:
parent
60eaabfb37
commit
801b6bec5f
|
@ -0,0 +1 @@
|
|||
BREAKING: GuardFilter is no longer an enum.
|
|
@ -1,7 +1,5 @@
|
|||
//! Implement GuardFilter and related types.
|
||||
|
||||
use educe::Educe;
|
||||
|
||||
use tor_linkspec::ChanTarget;
|
||||
|
||||
/// An object specifying which relays are eligible to be guards.
|
||||
|
@ -17,15 +15,17 @@ use tor_linkspec::ChanTarget;
|
|||
/// Right now, only the `Unrestricted` filter is implemented or available.
|
||||
/// This enumeration is just a place-holder, however, to make sure we're
|
||||
/// checking our filter in the right places.
|
||||
#[derive(Debug, Clone, Educe)]
|
||||
#[educe(Default)]
|
||||
#[non_exhaustive]
|
||||
pub enum GuardFilter {
|
||||
/// A filter representing no restrictions on the permissible guards
|
||||
/// at all.
|
||||
#[educe(Default)]
|
||||
Unfiltered,
|
||||
#[derive(Debug, Clone, Default)]
|
||||
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.
|
||||
filters: Vec<SingleFilter>,
|
||||
}
|
||||
|
||||
/// A single restriction places upon usable guards.
|
||||
#[derive(Debug, Clone)]
|
||||
enum SingleFilter {
|
||||
/// Testing only: checks whether the first byte of the rsa key is 0 modulo 4.
|
||||
///
|
||||
/// TODO: remove this once real filters are implemented.
|
||||
|
@ -38,21 +38,42 @@ impl GuardFilter {
|
|||
/// Create a new [`GuardFilter`] that doesn't restrict the set of
|
||||
/// permissible guards at all.
|
||||
pub fn unfiltered() -> Self {
|
||||
GuardFilter::Unfiltered
|
||||
GuardFilter::default()
|
||||
}
|
||||
|
||||
/// Return true if this filter permits the provided `target`.
|
||||
pub(crate) fn permits<C: ChanTarget>(&self, target: &C) -> bool {
|
||||
let _ = target; // ignored for now, since only Unfiltered exists.
|
||||
match self {
|
||||
GuardFilter::Unfiltered => true,
|
||||
#[cfg(test)]
|
||||
GuardFilter::TestingLimitKeys => target.rsa_identity().as_bytes()[0] & 3 == 0,
|
||||
}
|
||||
self.filters.iter().all(|filt| filt.permits(target))
|
||||
}
|
||||
|
||||
/// Return true if this filter excludes no guards at all.
|
||||
pub(crate) fn is_unfiltered(&self) -> bool {
|
||||
matches!(self, GuardFilter::Unfiltered)
|
||||
self.filters.is_empty()
|
||||
}
|
||||
|
||||
/// Add a restriction to this filter that keys must have their final two
|
||||
/// bits of their first byte are set to 0.
|
||||
///
|
||||
/// TODO: this testing-only, and is getting killed off once we have real filter
|
||||
#[cfg(test)]
|
||||
pub(crate) fn push_key_limit(&mut self) {
|
||||
self.filters.push(SingleFilter::TestingLimitKeys);
|
||||
}
|
||||
}
|
||||
|
||||
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::TestingLimitKeys => target.rsa_identity().as_bytes()[0] & 3 == 0,
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
let _ = target;
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1481,7 +1481,12 @@ mod test {
|
|||
let (guardmgr, _statemgr, netdir) = init(rt);
|
||||
let u = GuardUsage::default();
|
||||
guardmgr.update_network(&netdir);
|
||||
guardmgr.set_filter(GuardFilter::TestingLimitKeys, &netdir);
|
||||
let filter = {
|
||||
let mut f = GuardFilter::default();
|
||||
f.push_key_limit();
|
||||
f
|
||||
};
|
||||
guardmgr.set_filter(filter, &netdir);
|
||||
|
||||
let (guard, _mon, _usable) = guardmgr.select_guard(u, Some(&netdir)).unwrap();
|
||||
// Make sure that the filter worked.
|
||||
|
|
Loading…
Reference in New Issue