use rama_core::extensions::Extensions;
#[derive(Debug, Clone)]
pub struct LoopbackMatcher {
optional: bool,
}
impl LoopbackMatcher {
#[must_use]
pub const fn new() -> Self {
Self { optional: false }
}
#[must_use]
pub const fn optional() -> Self {
Self { optional: true }
}
}
impl Default for LoopbackMatcher {
fn default() -> Self {
Self::new()
}
}
impl<Socket> rama_core::matcher::Matcher<Socket> for LoopbackMatcher
where
Socket: crate::stream::Socket,
{
fn matches(&self, _ext: Option<&Extensions>, stream: &Socket) -> bool {
stream
.peer_addr()
.map(|addr| addr.ip_addr.is_loopback())
.unwrap_or(self.optional)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::address::SocketAddress;
use rama_core::matcher::Matcher;
#[test]
fn test_loopback_matcher_socket_trait() {
let matcher = LoopbackMatcher::new();
struct FakeSocket {
local_addr: Option<SocketAddress>,
peer_addr: Option<SocketAddress>,
}
impl crate::stream::Socket for FakeSocket {
fn local_addr(&self) -> std::io::Result<SocketAddress> {
match &self.local_addr {
Some(addr) => Ok(*addr),
None => Err(std::io::Error::from(std::io::ErrorKind::AddrNotAvailable)),
}
}
fn peer_addr(&self) -> std::io::Result<SocketAddress> {
match &self.peer_addr {
Some(addr) => Ok(*addr),
None => Err(std::io::Error::from(std::io::ErrorKind::AddrNotAvailable)),
}
}
}
let mut socket = FakeSocket {
local_addr: None,
peer_addr: None,
};
assert!(!matcher.matches(None, &socket));
socket.peer_addr = Some(([192, 168, 0, 1], 8080).into());
assert!(!matcher.matches(None, &socket));
socket.peer_addr = Some(([1, 1, 1, 1, 1, 1, 1, 1], 8080).into());
assert!(!matcher.matches(None, &socket));
socket.peer_addr = Some(([127, 0, 0, 1], 8080).into());
assert!(matcher.matches(None, &socket));
socket.peer_addr = Some(([127, 3, 2, 1], 8080).into());
assert!(matcher.matches(None, &socket));
socket.peer_addr = Some(([0, 0, 0, 0, 0, 0, 0, 1], 8080).into());
assert!(matcher.matches(None, &socket));
let matcher = LoopbackMatcher::optional();
socket.peer_addr = None;
assert!(matcher.matches(None, &socket));
}
}