use std::cmp::{PartialEq, Eq};
use std::net::SocketAddr;
use std::any::Any;
use message::protocol::Protocol;
use message::extensions::{Extensions};
use bip_util::bt::{InfoHash, PeerId};
pub mod filters;
pub trait HandshakeFilters {
fn add_filter<F>(&self, filter: F)
where F: HandshakeFilter + PartialEq + Eq + Send + Sync + 'static;
fn remove_filter<F>(&self, filter: F)
where F: HandshakeFilter + PartialEq + Eq + Send + Sync + 'static;
fn clear_filters(&self);
}
impl<'a, T> HandshakeFilters for &'a T where T: HandshakeFilters {
fn add_filter<F>(&self, filter: F)
where F: HandshakeFilter + PartialEq + Eq + Send + Sync + 'static {
(*self).add_filter(filter)
}
fn remove_filter<F>(&self, filter: F)
where F: HandshakeFilter + PartialEq + Eq + Send + Sync + 'static {
(*self).remove_filter(filter)
}
fn clear_filters(&self) {
(*self).clear_filters()
}
}
#[allow(unused)]
pub trait HandshakeFilter {
fn as_any(&self) -> &Any;
fn on_addr(&self, opt_addr: Option<&SocketAddr>) -> FilterDecision { FilterDecision::Pass }
fn on_prot(&self, opt_prot: Option<&Protocol>) -> FilterDecision { FilterDecision::Pass }
fn on_ext(&self, opt_ext: Option<&Extensions>) -> FilterDecision { FilterDecision::Pass }
fn on_hash(&self, opt_hash: Option<&InfoHash>) -> FilterDecision { FilterDecision::Pass }
fn on_pid(&self, opt_pid: Option<&PeerId>) -> FilterDecision { FilterDecision::Pass }
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum FilterDecision {
Pass = 0,
Block = 1,
NeedData = 2,
Allow = 3
}
impl FilterDecision {
pub fn choose(&self, other: FilterDecision) -> FilterDecision {
let self_num = *self as u8;
let other_num = other as u8;
if self_num > other_num {
*self
} else {
other
}
}
}
#[cfg(test)]
mod tests {
use super::FilterDecision;
#[test]
fn positive_decision_choose_self() {
let decision = FilterDecision::Block;
assert_eq!(FilterDecision::Block, decision.choose(FilterDecision::Block));
}
#[test]
fn positive_decision_choose_higher() {
let decision = FilterDecision::Pass;
assert_eq!(FilterDecision::NeedData, decision.choose(FilterDecision::NeedData));
}
#[test]
fn positive_decision_keep_higher() {
let decision = FilterDecision::NeedData;
assert_eq!(FilterDecision::NeedData, decision.choose(FilterDecision::Pass));
}
}