zenith-net 0.1.0

Zenith 网络地址与传输层抽象:L2-L4 协议解析、TCP/UDP/QUIC 状态机、来源准入引擎、单队列 Worker 数据面循环
//! Zenith Net - 网络地址与传输层抽象
//!
//! 本 crate 提供网络相关的类型和工具函数,包括:
//! - 套接字地址封装(Copy 类型,零堆分配)
//! - 网络接口信息
//! - 传输层协议抽象
//! - L2/L3/L4 协议解析
//! - 来源准入引擎
//! - 单队列 Worker 数据面循环
//!
//! # unsafe 边界声明(AGENT.md §1.1 例外条款)
//!
//! 本 crate 顶层 `#![deny(unsafe_code)]`。唯一例外为 `packet` 模块内的 `cast` 子模块:
//! `#[repr(C, packed)]` 协议头结构体与字节切片间的裸指针转换是零拷贝语义的内在要求,
//! 无法用 safe Rust 表达。该子模块在文件顶部以 `#![allow(unsafe_code)]` 精确放开,
//! 每个 unsafe 块均附 `// SAFETY:` 行内注释。详见 [packet::cast] 模块文档。

#![deny(unsafe_code)]
#![deny(missing_debug_implementations)]
#![warn(missing_docs)]

pub mod error;
#[allow(unsafe_code)]
pub mod packet;
pub mod protocol_expectation;
pub mod source_admission;
pub mod transport;

#[cfg(all(feature = "linux", target_os = "linux"))]
pub mod worker;
// 非 Linux 目标(或未启用 linux feature):提供同 API 表面的可移植桩,
// 帧池/准入/状态机真实可用,数据面 process_cycle fail-closed
#[cfg(not(all(feature = "linux", target_os = "linux")))]
#[path = "worker_stub.rs"]
pub mod worker;

pub use error::{NetError, Result};
pub use packet::{
    parse_packet, parse_tcp_options, EthHeader, Ipv4Header, Ipv6Header, IpVersion, L4Protocol,
    ParsedPacket, TcpHeader, TcpOptionsInfo, UdpHeader, VlanTag,
};
pub use protocol_expectation::ProtocolExpectation;
pub use source_admission::{
    AdmissionAction, AdmissionRule, IpAddr, ProtoMatch, SourceAdmissionEngine,
};
pub use transport::{
    Accept, AcceptedConn, AcceptError, BindTable, ConnectionKey, ConnectionState, ListenEndpoint,
    StdTcpAcceptor, TcpAction, TcpConnection, TcpStateMachine, TcpStats, UdpAction, UdpMode,
    UdpSession, UdpSessionTable, UdpStats, BIND_TABLE_CAPACITY,
    QuicAction, QuicConnParams, QuicConnState, QuicConnection, QuicConnectionTable,
    QuicFrameType, QuicHeader, QuicHeaderType, QuicStream, QuicStreamState,
    PathChallengeFrame, PathResponseFrame, PathValidationState,
    parse_quic_header, parse_path_challenge_frame, parse_path_response_frame,
    // QUIC 服务器(真实传输层)
    QuicServer, QuicServerConfig, QuicServerError, QuicServerState,
    QuicServerConnection, QuicServerFrame, QuicVersion,
    build_ack_frame, build_connection_close_app, build_connection_close_transport, build_crypto_frame, build_handshake_done_frame,
    build_padding_frame, build_ping_frame, build_stream_frame, build_default_transport_params,
    decode_packet_number, parse_frame, parse_frames, parse_long_header_full,
    parse_short_header, ParsedLongHeader, ParsedShortHeader,
    TimerAction, TimerType, TimerWheel,
};

// Worker/WorkerState/WorkerStats 在真实实现与可移植桩中均提供,无条件导出
pub use worker::{Worker, WorkerState, WorkerStats};
// UdpDatagram 仅真实 AF_XDP 数据面提供(桩模式无 L7 数据出口)
#[cfg(all(feature = "linux", target_os = "linux"))]
pub use worker::UdpDatagram;

/// 网络地址族
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AddressFamily {
    /// IPv4
    Ipv4,
    /// IPv6
    Ipv6,
}

/// 统一网络地址(Copy 类型,零堆分配)
///
/// 使用固定字节数组存储 IP,避免 String 堆分配。
/// IPv4 使用 [u8; 4],IPv6 使用 [u8; 16](仅使用前 4 字节在 IPv4 模式下)。
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct NetAddr {
    /// IPv4 地址字节
    ipv4: [u8; 4],
    /// IPv6 地址字节
    ipv6: [u8; 16],
    /// 端口号
    port: u16,
    /// 地址族
    family: AddressFamily,
}

impl NetAddr {
    /// 创建新的网络地址(IPv4)
    pub fn new_ipv4(ip: [u8; 4], port: u16) -> Self {
        Self {
            ipv4: ip,
            ipv6: [0u8; 16],
            port,
            family: AddressFamily::Ipv4,
        }
    }

    /// 创建新的网络地址(IPv6)
    pub fn new_ipv6(ip: [u8; 16], port: u16) -> Self {
        Self {
            ipv4: [0u8; 4],
            ipv6: ip,
            port,
            family: AddressFamily::Ipv6,
        }
    }

    /// 从 source_admission::IpAddr 创建
    pub fn from_ip_addr(ip: IpAddr, port: u16) -> Self {
        match ip {
            IpAddr::V4(bytes) => Self::new_ipv4(bytes, port),
            IpAddr::V6(bytes) => Self::new_ipv6(bytes, port),
            // NET-019:跨族通配无具体地址,映射为 IPv4 通配地址(0.0.0.0)
            IpAddr::Any => Self::new_ipv4([0, 0, 0, 0], port),
        }
    }

    /// 获取地址族
    #[inline]
    pub fn family(&self) -> AddressFamily {
        self.family
    }

    /// 获取端口
    #[inline]
    pub fn port(&self) -> u16 {
        self.port
    }

    /// 获取 IPv4 地址字节
    #[inline]
    pub fn ipv4_bytes(&self) -> [u8; 4] {
        self.ipv4
    }

    /// 获取 IPv6 地址字节
    #[inline]
    pub fn ipv6_bytes(&self) -> [u8; 16] {
        self.ipv6
    }

    /// 转换为 source_admission::IpAddr
    #[inline]
    pub fn to_ip_addr(&self) -> IpAddr {
        match self.family {
            AddressFamily::Ipv4 => IpAddr::V4(self.ipv4),
            AddressFamily::Ipv6 => IpAddr::V6(self.ipv6),
        }
    }

    /// 获取地址字符串表示(格式化为 String,仅在调试/日志路径使用)
    pub fn to_string_addr(&self) -> String {
        match self.family {
            AddressFamily::Ipv4 => {
                format!("{}.{}.{}.{}:{}", self.ipv4[0], self.ipv4[1], self.ipv4[2], self.ipv4[3], self.port)
            }
            AddressFamily::Ipv6 => {
                // hex 编码:委托 zenith-core 统一实现
                let hex = zenith_foundation::hex_encode(&self.ipv6);
                format!("[{}]:{}", hex, self.port)
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_net_addr_ipv4() {
        let addr = NetAddr::new_ipv4([127, 0, 0, 1], 8080);
        assert_eq!(addr.ipv4_bytes(), [127, 0, 0, 1]);
        assert_eq!(addr.port(), 8080);
        assert_eq!(addr.family(), AddressFamily::Ipv4);
        assert_eq!(addr.to_string_addr(), "127.0.0.1:8080");
    }

    #[test]
    fn test_net_addr_ipv6() {
        let addr = NetAddr::new_ipv6([0u8; 16], 443);
        assert_eq!(addr.family(), AddressFamily::Ipv6);
        assert_eq!(addr.port(), 443);
    }

    #[test]
    fn test_net_addr_equality() {
        let a = NetAddr::new_ipv4([10, 0, 0, 1], 80);
        let b = NetAddr::new_ipv4([10, 0, 0, 1], 80);
        assert_eq!(a, b);
    }

    #[test]
    fn test_net_addr_from_ip_addr() {
        let ip = IpAddr::V4([192, 168, 1, 1]);
        let addr = NetAddr::from_ip_addr(ip, 8080);
        assert_eq!(addr.ipv4_bytes(), [192, 168, 1, 1]);
        assert_eq!(addr.port(), 8080);

        let addr2 = NetAddr::from_ip_addr(IpAddr::V4_WILDCARD, 0);
        assert_eq!(addr2.ipv4_bytes(), [0, 0, 0, 0]);
    }

    #[test]
    fn test_net_addr_copy_semantics() {
        let addr = NetAddr::new_ipv4([1, 2, 3, 4], 8080);
        let copy = addr;
        // 验证 Copy 语义
        assert_eq!(addr, copy);
        assert_eq!(addr.port(), 8080);
    }

    #[test]
    fn test_net_addr_to_ip_addr() {
        let addr = NetAddr::new_ipv4([10, 20, 30, 40], 80);
        let ip = addr.to_ip_addr();
        assert_eq!(ip, IpAddr::V4([10, 20, 30, 40]));
    }
}