///|
/// 传输层协议
pub(all) enum Proto {
Tcp
Udp
Icmp
Icmpv6
Other
} derive(Eq, Hash)
///|
/// 包方向(Local = 本机到本机,如回环)
pub(all) enum Direction {
In
Out
Local
}
///|
/// IP 地址(v4 = 4 字节,v6 = 16 字节)
pub struct IpAddr {
v4 : Bool
bytes : Bytes
} derive(Eq, Hash, Compare)
///|
/// 构造 IP 地址
pub fn IpAddr::new(v4 : Bool, bytes : Bytes) -> IpAddr {
{ v4, bytes }
}
///|
/// 五元组(连接跟踪的 key)
pub struct FiveTuple {
src_ip : IpAddr
dst_ip : IpAddr
src_port : Int
dst_port : Int
proto : Proto
} derive(Eq, Hash)
///|
/// 构造五元组
pub fn FiveTuple::new(
src_ip : IpAddr,
dst_ip : IpAddr,
src_port : Int,
dst_port : Int,
proto : Proto,
) -> FiveTuple {
{ src_ip, dst_ip, src_port, dst_port, proto }
}
///|
/// 解析结果:时间戳 + 五元组 + 方向 + 载荷长度(供流量统计)
pub struct ParsedPacket {
ts_sec : Int64
ts_usec : Int
tuple : FiveTuple
direction : Direction
payload_len : Int
total_len : Int
}
///|
/// 构造解析结果
pub fn ParsedPacket::new(
ts_sec : Int64,
ts_usec : Int,
tuple : FiveTuple,
direction : Direction,
payload_len : Int,
total_len : Int,
) -> ParsedPacket {
{ ts_sec, ts_usec, tuple, direction, payload_len, total_len }
}
///|
pub fn Proto::to_string(self : Proto) -> String {
match self {
Tcp => "tcp"
Udp => "udp"
Icmp => "icmp"
Icmpv6 => "icmpv6"
Other => "other"
}
}
///|
pub fn Direction::to_string(self : Direction) -> String {
match self {
In => "in"
Out => "out"
Local => "local"
}
}
///|
pub fn IpAddr::to_string(self : IpAddr) -> String {
let b = self.bytes
if self.v4 {
"\{b[0].to_int()}.\{b[1].to_int()}.\{b[2].to_int()}.\{b[3].to_int()}"
} else {
// IPv6:8 组,组内省略前导零(不压缩 :: 段)
// 每组 4 位 hex,省略前导零(全零组保留 "0")
let parts : Array[String] = []
for i in 0..<8 {
let g = b[i * 2].to_hex() + b[i * 2 + 1].to_hex()
parts.push(
if g == "0000" {
"0"
} else {
g.trim_start(chars="0").to_owned()
},
)
}
parts.join(":")
}
}
///|
pub fn FiveTuple::to_string(self : FiveTuple) -> String {
"\{self.src_ip.to_string()}:\{self.src_port} -> \{self.dst_ip.to_string()}:\{self.dst_port} \{self.proto.to_string()}"
}
///|
/// 本机 IP 集合查找
fn contains_ip(ips : FixedArray[IpAddr], ip : IpAddr) -> Bool {
ips.iter().any(fn(a) { a == ip })
}
///|
/// 方向判定:src 本机 + dst 外部 → Out;反 → In;都本机 → Local
pub fn direction(
src : IpAddr,
dst : IpAddr,
local_ips : FixedArray[IpAddr],
) -> Direction {
match (contains_ip(local_ips, src), contains_ip(local_ips, dst)) {
(true, true) => Local
(true, false) => Out
_ => In
}
}