use serde::Deserialize;
use std::net::IpAddr;
use thiserror::Error;
use tokio::sync::mpsc; use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::Mutex as AsyncMutex;
use std::path::PathBuf;
use tokio::sync::oneshot;
use bollard;
#[derive(Error, Debug)]
pub enum AppError {
#[error("Configuration parsing error: {0}")]
ConfigParse(#[from] serde_yaml::Error),
#[error("Configuration file IO error: {0}")]
ConfigIo(String),
#[error("Configuration validation error: {0}")]
ConfigValidation(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Nftables helper error: {0}")]
NftablesError(#[from] nftables::helper::NftablesError),
#[error("Docker interaction error: {0}")]
DockerError(String),
#[error("Error receiving Docker event stream: {0}")]
DockerStream(#[from] bollard::errors::Error),
#[error("Netlink error: {0}")]
Netlink(String),
#[error("RtNetlink error: {0}")]
RtNetlink(#[from] rtnetlink::Error),
#[error("Tokio MPSC channel send error: {0}")]
MpscSendError(String),
#[error("Channel receive error: {0}")]
ChannelRecvError(String),
#[error("Oneshot channel send error: {0}")]
OneshotSendError(String),
#[error("Anyhow error: {0}")]
Anyhow(#[from] anyhow::Error),
}
pub type Result<T> = std::result::Result<T, AppError>;
#[derive(Debug, Deserialize, Clone)]
pub struct InterfaceConfig {
pub name: String,
pub dhcp: Option<bool>, pub address: Option<String>, pub nftables_zone: Option<String>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct AppConfig {
pub interfaces: Vec<InterfaceConfig>,
pub socket_path: Option<String>,
pub nftables_rules_path: Option<String>, }
#[derive(Debug, Default, Clone)]
pub struct NetworkState {
pub interface_ips: HashMap<String, Vec<IpAddr>>, pub if_index_to_name: HashMap<u32, String>,
}
#[derive(Debug, Default)] pub struct AppStateShared {
pub config: Arc<AsyncMutex<Vec<InterfaceConfig>>>,
pub network_state: Arc<AsyncMutex<NetworkState>>,
pub container_ips: Arc<AsyncMutex<HashMap<String, Option<IpAddr>>>>,
}
#[derive(Debug, Clone)]
pub enum NetworkEvent {
IpUpdate { interface: String, ips: Vec<IpAddr> },
LinkChanged { name: String, is_up: bool },
}
#[derive(Debug)]
pub enum ControlCommand {
Reload,
Status { response_tx: oneshot::Sender<String> },
Ping { response_tx: oneshot::Sender<String> },
Shutdown, }
pub type EventSender = mpsc::Sender<SystemEvent>;
pub type EventReceiver = mpsc::Receiver<SystemEvent>;
#[derive(Debug, Clone)]
pub enum DockerEvent {
ContainerStarted(String, Option<IpAddr>), ContainerStopped(String), }
#[derive(Debug)]
pub enum SystemEvent {
Network(NetworkEvent),
Docker(DockerEvent),
Control(ControlCommand),
Signal(i32),
}
impl From<ControlCommand> for SystemEvent {
fn from(cmd: ControlCommand) -> Self {
SystemEvent::Control(cmd)
}
}