scylla/policies/
host_filter.rs

1//! Host filters.
2//!
3//! Host filters are essentially just a predicate over
4//! [`Peer`]s. Currently, they are used
5//! by the [`Session`](crate::client::session::Session) to determine whether
6//! connections should be opened to a given node or not.
7
8use std::collections::HashSet;
9use std::io::Error;
10use std::net::{SocketAddr, ToSocketAddrs};
11
12use crate::cluster::metadata::Peer;
13
14/// The `HostFilter` trait.
15pub trait HostFilter: Send + Sync {
16    /// Returns whether a peer should be accepted or not.
17    fn accept(&self, peer: &Peer) -> bool;
18}
19
20/// Unconditionally accepts all nodes.
21pub struct AcceptAllHostFilter;
22
23impl HostFilter for AcceptAllHostFilter {
24    fn accept(&self, _peer: &Peer) -> bool {
25        true
26    }
27}
28
29/// Accepts nodes whose addresses are present in the allow list provided
30/// during filter's construction.
31pub struct AllowListHostFilter {
32    allowed: HashSet<SocketAddr>,
33}
34
35impl AllowListHostFilter {
36    /// Creates a new `AllowListHostFilter` which only accepts nodes from the
37    /// list.
38    pub fn new<I, A>(allowed_iter: I) -> Result<Self, Error>
39    where
40        I: IntoIterator<Item = A>,
41        A: ToSocketAddrs,
42    {
43        // I couldn't get the iterator combinators to work
44        let mut allowed = HashSet::new();
45        for item in allowed_iter {
46            for addr in item.to_socket_addrs()? {
47                allowed.insert(addr);
48            }
49        }
50
51        Ok(Self { allowed })
52    }
53}
54
55impl HostFilter for AllowListHostFilter {
56    fn accept(&self, peer: &Peer) -> bool {
57        match peer.address {
58            crate::cluster::NodeAddr::Translatable(addr) => self.allowed.contains(&addr),
59            // If the address is Untranslatable, then the node either was originally
60            // an ContactPoint, or a Translatable node for which the host filter
61            // returned true.
62            crate::cluster::NodeAddr::Untranslatable(_) => true,
63        }
64    }
65}
66
67/// Accepts nodes from given DC.
68pub struct DcHostFilter {
69    local_dc: String,
70}
71
72impl DcHostFilter {
73    /// Creates a new `DcHostFilter` that accepts nodes only from the
74    /// `local_dc`.
75    pub fn new(local_dc: String) -> Self {
76        Self { local_dc }
77    }
78}
79
80impl HostFilter for DcHostFilter {
81    fn accept(&self, peer: &Peer) -> bool {
82        peer.datacenter.as_ref() == Some(&self.local_dc)
83    }
84}