use std::sync::Arc;
use multiaddr::{Multiaddr, Protocol};
use crate::transports::predicate::Predicate;
#[derive(Debug, Clone)]
pub struct TorProxyOpts {
pub bypass_addresses: Arc<Vec<Multiaddr>>,
pub bypass_for_tcpip: bool,
}
impl TorProxyOpts {
pub fn to_bypass_predicate(&self) -> impl Predicate<Multiaddr> + Send + Sync + 'static {
let config = self.clone();
move |addr: &Multiaddr| -> bool {
config.bypass_addresses.contains(addr) || (config.bypass_for_tcpip && is_tcp_address(addr))
}
}
}
impl Default for TorProxyOpts {
fn default() -> Self {
Self {
bypass_addresses: Arc::new(vec![]),
bypass_for_tcpip: false,
}
}
}
fn is_tcp_address(addr: &Multiaddr) -> bool {
use Protocol::{Dns4, Dns6, Ip4, Ip6, Tcp};
let mut iter = addr.iter();
let protocol = iter.next();
if !matches!(protocol, Some(Ip4(_)) | Some(Ip6(_)) | Some(Dns4(_)) | Some(Dns6(_))) {
return false;
}
let protocol = iter.next();
matches!(protocol, Some(Tcp(_)))
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn is_tcpip_address() {
let expect_false = [
"/onion/aaimaq4ygg2iegci:1234",
"/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:1234",
];
let expect_true = [
"/ip4/1.2.3.4/tcp/1234",
"/ip4/127.0.0.1/tcp/9998",
"/dns4/tari.com/tcp/80",
];
expect_true.iter().for_each(|addr| {
let addr = addr.parse().unwrap();
assert!(super::is_tcp_address(&addr));
});
expect_false.iter().for_each(|addr| {
let addr = addr.parse().unwrap();
assert!(!super::is_tcp_address(&addr));
});
}
#[test]
fn proxy_opts() {
let expect_false = [
"/onion/aaimaq4ygg2iegci:1234",
"/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:1234",
]
.iter()
.map(|a| a.parse().unwrap())
.collect::<Vec<Multiaddr>>();
let expect_true = [
"/ip4/1.2.3.4/tcp/1234",
"/ip4/127.0.0.1/tcp/9998",
"/dns4/tari.com/tcp/80",
]
.iter()
.map(|a| a.parse().unwrap())
.collect::<Vec<Multiaddr>>();
let opts = TorProxyOpts {
bypass_addresses: expect_false.clone().into(),
..Default::default()
};
let predicate = opts.to_bypass_predicate();
expect_false.iter().for_each(|addr| {
assert!(predicate.check(addr));
});
expect_true.iter().for_each(|addr| {
assert!(!predicate.check(addr));
});
let opts = TorProxyOpts {
bypass_for_tcpip: true,
..Default::default()
};
let predicate = opts.to_bypass_predicate();
expect_true.iter().for_each(|addr| {
assert!(predicate.check(addr));
});
expect_false.iter().for_each(|addr| {
assert!(!predicate.check(addr));
});
}
}