use std::time::Instant;
use async_trait::async_trait;
use crate::{actions::FilterAction, filter::FilterError};
#[async_trait]
pub trait TcpFilter: Send + Sync {
fn name(&self) -> &'static str;
async fn on_connect(&self, ctx: &mut TcpFilterContext<'_>) -> Result<FilterAction, FilterError> {
let _ = ctx;
Ok(FilterAction::Continue)
}
async fn on_disconnect(&self, ctx: &mut TcpFilterContext<'_>) -> Result<(), FilterError> {
let _ = ctx;
Ok(())
}
}
pub struct TcpFilterContext<'a> {
pub remote_addr: &'a str,
pub local_addr: &'a str,
pub upstream_addr: &'a str,
pub connect_time: Instant,
pub bytes_in: u64,
pub bytes_out: u64,
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn default_on_connect_returns_continue() {
let filter = NoopTcpFilter;
let mut ctx = TcpFilterContext {
remote_addr: "127.0.0.1:12345",
local_addr: "0.0.0.0:5432",
upstream_addr: "10.0.0.1:5432",
connect_time: Instant::now(),
bytes_in: 0,
bytes_out: 0,
};
let action = filter.on_connect(&mut ctx).await.unwrap();
assert!(matches!(action, FilterAction::Continue));
}
#[tokio::test]
async fn default_on_disconnect_succeeds() {
let filter = NoopTcpFilter;
let mut ctx = TcpFilterContext {
remote_addr: "127.0.0.1:12345",
local_addr: "0.0.0.0:5432",
upstream_addr: "10.0.0.1:5432",
connect_time: Instant::now(),
bytes_in: 0,
bytes_out: 0,
};
filter.on_disconnect(&mut ctx).await.unwrap();
}
struct NoopTcpFilter;
#[async_trait]
impl TcpFilter for NoopTcpFilter {
fn name(&self) -> &'static str {
"noop_tcp"
}
}
}