ouisync/network/
addr_filter.rs

1use std::net::SocketAddr;
2
3use super::ip;
4
5/// Filters out certain types of socket addresses which are unlikely to belong to valid peers (e.g.,
6/// addresses from reserved ranges, etc...)
7///
8/// Using non-default filter typically only makes sense for testing (e.g., when using
9/// [patchbay](https://crates.io/crates/patchbay) which allocates IPs from the "benchmarking"
10/// range).
11#[derive(Clone, Copy, Debug)]
12#[non_exhaustive]
13pub struct AddrFilter {
14    /// Whether
15    /// [benchmarking](https://doc.rust-lang.org/beta/std/net/struct.Ipv4Addr.html#method.is_benchmarking)
16    /// IPv4 addresses are allowed. Default is `false`.
17    pub allow_benchmarking_v4: bool,
18}
19
20impl AddrFilter {
21    pub fn allow_benchmarking_v4(self) -> Self {
22        Self {
23            allow_benchmarking_v4: true,
24        }
25    }
26}
27
28#[expect(clippy::derivable_impls)] // we want to be explicit here
29impl Default for AddrFilter {
30    fn default() -> Self {
31        Self {
32            allow_benchmarking_v4: false,
33        }
34    }
35}
36
37impl AddrFilter {
38    /// Apply the filter to the address. Returns whether the address passes the filter.
39    pub(super) fn apply(&self, addr: &SocketAddr) -> bool {
40        if addr.port() == 0 || addr.port() == 1 {
41            return false;
42        }
43
44        match addr {
45            SocketAddr::V4(addr) => {
46                let ip_addr = addr.ip();
47                if ip_addr.octets()[0] == 0 {
48                    return false;
49                }
50                if (!self.allow_benchmarking_v4 && ip::is_benchmarking(ip_addr))
51                    || ip::is_reserved(ip_addr)
52                    || ip_addr.is_broadcast()
53                    || ip_addr.is_documentation()
54                {
55                    return false;
56                }
57            }
58            SocketAddr::V6(addr) => {
59                let ip_addr = addr.ip();
60
61                if ip_addr.is_multicast()
62                    || ip_addr.is_unspecified()
63                    || ip::is_documentation(ip_addr)
64                {
65                    return false;
66                }
67            }
68        }
69
70        true
71    }
72}