mod facts;
mod http_port;
mod https;
mod listeners;
mod routes;
mod scans;
use std::collections::HashMap;
use std::net::Ipv4Addr;
use std::sync::{Arc, RwLock};
use tokio::sync::mpsc;
use tokio::task::JoinHandle;
use tokio_util::sync::CancellationToken;
pub use self::facts::ContainerFacts;
use self::routes::Routes;
const RULE_OWNER: &str = "arcbox-domain:";
#[derive(Clone, Default)]
struct HttpPorts(Arc<RwLock<HashMap<Ipv4Addr, u16>>>);
impl HttpPorts {
fn route(&self, ips: &[Ipv4Addr], port: Option<u16>) {
let mut ports = self.0.write().expect("HTTP port table lock poisoned");
for ip in ips {
match port {
Some(port) => ports.insert(*ip, port),
None => ports.remove(ip),
};
}
}
fn get(&self, ip: Ipv4Addr) -> Option<u16> {
let ports = self.0.read().expect("HTTP port table lock poisoned");
ports.get(&ip).copied()
}
}
pub struct DomainRoutes {
commands: mpsc::UnboundedSender<Command>,
}
enum Command {
Track(ContainerFacts),
Forget(String),
}
impl DomainRoutes {
#[must_use]
pub fn spawn(cancel: CancellationToken) -> (Self, JoinHandle<()>) {
let (commands, inbox) = mpsc::unbounded_channel();
let task = tokio::spawn(Routes::new().run(inbox, cancel));
(Self { commands }, task)
}
pub fn track(&self, facts: ContainerFacts) {
let _ = self.commands.send(Command::Track(facts));
}
pub fn forget(&self, container_id: &str) {
let _ = self.commands.send(Command::Forget(container_id.to_owned()));
}
}