///|
/// pcap 句柄
pub struct Pcap {
handle : Int64
}
///|
extern "c" fn npcap_load() -> Int = "npcap_load"
///|
extern "c" fn npcap_findalldevs() -> Int = "npcap_findalldevs"
///|
extern "c" fn npcap_dev_name(i : Int) -> String = "npcap_dev_name"
///|
extern "c" fn npcap_dev_desc(i : Int) -> String = "npcap_dev_desc"
///|
extern "c" fn npcap_devs_free() -> Unit = "npcap_devs_free"
///|
#borrow(dev)
extern "c" fn npcap_open_live(
dev : String,
snaplen : Int,
promisc : Int,
timeout : Int,
) -> Int64 = "npcap_open_live"
///|
extern "c" fn npcap_datalink(p : Int64) -> Int = "npcap_datalink"
///|
extern "c" fn npcap_errbuf() -> String = "npcap_errbuf"
///|
extern "c" fn npcap_geterr(p : Int64) -> String = "npcap_geterr"
///|
extern "c" fn npcap_breakloop(p : Int64) -> Unit = "npcap_breakloop"
///|
extern "c" fn npcap_close(p : Int64) -> Unit = "npcap_close"
///|
extern "c" fn npcap_next_ex(p : Int64) -> Int = "npcap_next_ex"
///|
extern "c" fn npcap_ts_sec() -> Int64 = "npcap_ts_sec"
///|
extern "c" fn npcap_ts_usec() -> Int64 = "npcap_ts_usec"
///|
extern "c" fn npcap_caplen() -> Int64 = "npcap_caplen"
///|
extern "c" fn npcap_len() -> Int64 = "npcap_len"
///|
extern "c" fn npcap_data() -> Bytes = "npcap_data"
///|
extern "c" fn npcap_stdout_unbuffered() -> Unit = "npcap_stdout_unbuffered"
///|
#borrow(s)
extern "c" fn npcap_eprint(s : String) -> Unit = "npcap_eprint"
///|
extern "c" fn npcap_local_ips() -> Int = "npcap_local_ips"
///|
extern "c" fn npcap_local_ip(i : Int) -> Bytes = "npcap_local_ip"
///|
extern "c" fn npcap_local_ips_free() -> Unit = "npcap_local_ips_free"
///|
/// 加载 wpcap.dll(进程只需一次;失败原因映射见 npcap_load 返回值约定)
pub fn load() -> Result[Unit, String] {
match npcap_load() {
0 => Ok(())
-2 =>
Err(
"未检测到 Npcap:wpcap.dll 不存在,请先安装 Npcap(https://npcap.com)",
)
-1 => Err("wpcap.dll 加载失败(系统错误)")
_ => Err("wpcap.dll 版本不兼容:缺少所需导出函数")
}
}
///|
/// 枚举本机网卡(无设备或失败返回空数组)
pub fn devices() -> Array[Device] {
let n = npcap_findalldevs()
if n <= 0 {
return []
}
let arr = Array::makei(n, fn(i) {
{ name: npcap_dev_name(i), description: npcap_dev_desc(i) }
})
npcap_devs_free()
arr
}
///|
/// stdout 设为无缓冲(管道/重定向时 JSON 行立即输出)
pub fn stdout_unbuffered() -> Unit {
npcap_stdout_unbuffered()
}
///|
/// 日志输出到 stderr(stdout 专供 JSON 流)
pub fn eprint(msg : String) -> Unit {
npcap_eprint(msg)
}
///|
/// 枚举本机 IP 地址(GetAdaptersAddresses):(是否 IPv4, 地址字节),v4=4 字节 v6=16 字节
pub fn local_ips() -> Array[(Bool, Bytes)] {
let n = npcap_local_ips()
if n <= 0 {
return []
}
let arr = Array::makei(n, fn(i) {
let b = npcap_local_ip(i)
(b.length() == 4, b)
})
npcap_local_ips_free()
arr
}
///|
/// 打开设备(snaplen 抓包长度上限,promisc 混杂模式,timeout_ms 收包超时)
pub fn open(
dev : String,
snaplen : Int,
promisc : Bool,
timeout_ms : Int,
) -> Result[Pcap, String] {
let p = npcap_open_live(dev, snaplen, promisc.to_int(), timeout_ms)
if p == 0L {
Err(npcap_errbuf())
} else {
Ok({ handle: p })
}
}
///|
/// 链路层类型(1 = Ethernet / DLT_EN10MB)
pub fn datalink(p : Pcap) -> Int {
npcap_datalink(p.handle)
}
///|
/// 轮询收包:Some = 数据包,None = 超时或错误
pub fn next(p : Pcap) -> PacketRaw? {
match npcap_next_ex(p.handle) {
1 =>
Some({
ts_sec: npcap_ts_sec(),
ts_usec: npcap_ts_usec().to_int(),
caplen: npcap_caplen().to_int(),
len: npcap_len().to_int(),
data: npcap_data(),
})
_ => None
}
}
///|
/// 最近一次操作的错误信息
pub fn geterr(p : Pcap) -> String {
npcap_geterr(p.handle)
}
///|
/// 停止收包循环并关闭设备
pub fn close(p : Pcap) -> Unit {
npcap_breakloop(p.handle)
npcap_close(p.handle)
}