bcap/bcap.go

1360 lines
48 KiB
Go
Raw Normal View History

2024-11-24 11:30:27 +08:00
package bcap
import (
"fmt"
"net"
2026-02-04 13:33:54 +08:00
"strings"
2024-11-24 11:30:27 +08:00
"sync"
2026-02-04 13:33:54 +08:00
"sync/atomic"
"time"
"github.com/gopacket/gopacket"
"github.com/gopacket/gopacket/layers"
2024-11-24 11:30:27 +08:00
)
2026-02-04 13:33:54 +08:00
// ════════════════════════════════════════════════
// 错误类型定义 / Error Type Definitions
// ════════════════════════════════════════════════
// ParseErrorType 解析错误类型 / Parse error type
type ParseErrorType int
const (
ErrTypeNone ParseErrorType = iota // 无错误 / No error
ErrTypeLinkLayer // 链路层错误 / Link layer error
ErrTypeNetwork // 网络层错误 / Network layer error
ErrTypeTransport // 传输层错误 / Transport layer error
ErrTypeUnsupported // 不支持的协议 / Unsupported protocol
)
// ParseError 解析错误结构体,包含详细的错误信息
// ParseError structure containing detailed error information
type ParseError struct {
Type ParseErrorType // 错误类型 / Error type
Layer string // 出错的层 / Layer where error occurred
Message string // 错误信息 / Error message
Err error // 原始错误 / Original error
}
func (e *ParseError) Error() string {
if e.Err != nil {
return fmt.Sprintf("[%s] %s: %v", e.Layer, e.Message, e.Err)
}
return fmt.Sprintf("[%s] %s", e.Layer, e.Message)
}
// NewParseError 创建新的解析错误 / Create new parse error
func NewParseError(errType ParseErrorType, layer, message string, err error) *ParseError {
return &ParseError{
Type: errType,
Layer: layer,
Message: message,
Err: err,
}
}
// ════════════════════════════════════════════════
// 状态常量定义 / State Constants
// ════════════════════════════════════════════════════════════════════════════════
// TCP 状态描述符定义 / TCP state descriptor definitions
const (
StateUnknown uint8 = 0 // 未知状态 / Unknown state
StateTcpConnect1 uint8 = 1 // 三次握手第一步 (SYN) / Three-way handshake step 1 (SYN)
StateTcpConnect2 uint8 = 2 // 三次握手第二步 (SYN-ACK) / Three-way handshake step 2 (SYN-ACK)
StateTcpConnect3 uint8 = 3 // 三次握手第三步 (ACK) / Three-way handshake step 3 (ACK)
StateTcpDisconnect1 uint8 = 4 // 四次挥手第一步 (FIN) / Four-way handshake step 1 (FIN)
StateTcpDisconnect2 uint8 = 5 // 四次挥手第二步 (ACK) / Four-way handshake step 2 (ACK)
StateTcpDisconnect23 uint8 = 6 // 四次挥手第二三步合并 (FIN-ACK) / Four-way handshake step 2+3 combined
StateTcpDisconnect3 uint8 = 7 // 四次挥手第三步 (FIN) / Four-way handshake step 3 (FIN)
StateTcpDisconnect4 uint8 = 8 // 四次挥手第四步 (ACK) / Four-way handshake step 4 (ACK)
StateTcpAckOk uint8 = 9 // 正常 ACK / Normal ACK
StateTcpRetransmit uint8 = 10 // TCP 重传 / TCP retransmission
StateTcpEce uint8 = 11 // TCP ECE 标志 / TCP ECE flag
StateTcpCwr uint8 = 12 // TCP CWR 标志 / TCP CWR flag
StateTcpRst uint8 = 13 // TCP RST 标志 / TCP RST flag
StateTcpKeepalive uint8 = 14 // TCP 保活 / TCP keepalive
StateUdp uint8 = 20 // UDP 数据包 / UDP packet
StateIcmp uint8 = 30 // ICMP 数据包 / ICMP packet
StateIcmpv6 uint8 = 31 // ICMPv6 数据包 / ICMPv6 packet
)
// 默认配置常量 / Default configuration constants
const (
DefaultConnectionTimeout = 5 * time.Minute // 默认连接超时时间 / Default connection timeout
DefaultCleanupInterval = 1 * time.Minute // 默认清理间隔 / Default cleanup interval
DefaultShardCount = 32 // 默认分片数量 / Default shard count
)
// ════════════════════════════════════════════════
// 回调函数类型定义 / Callback Function Types
// ════════════════════════════════════════════════
// ConnectionCallback 连接事件回调函数类型
// ConnectionCallback connection event callback function type
type ConnectionCallback func(info PacketInfo)
// ErrorCallback 错误事件回调函数类型
// ErrorCallback error event callback function type
type ErrorCallback func(err *ParseError, packet gopacket.Packet)
// ════════════════════════════════════════════════════════════════════════════════
// 配置结构体 / Configuration Structures
// ════════════════════════════════════════════════════════════════════════════════
// PacketsConfig 数据包管理器配置
// PacketsConfig configuration for packets manager
type PacketsConfig struct {
// 连接超时时间,超过此时间未活动的连接将被清理
// Connection timeout, connections inactive beyond this time will be cleaned up
ConnectionTimeout time.Duration
// 自动清理间隔,设置为 0 则禁用自动清理
// Auto cleanup interval, set to 0 to disable auto cleanup
CleanupInterval time.Duration
// 是否启用懒加载模式(按需解析详细信息)
// Whether to enable lazy parsing mode (parse details on demand)
LazyParsing bool
// 是否启用调试日志
// Whether to enable debug logging
EnableDebugLog bool
// 分片数量(用于减少锁竞争)
// Shard count (for reducing lock contention)
ShardCount int
// 新连接回调 / New connection callback
OnNewConnection ConnectionCallback
// 连接关闭回调 / Connection closed callback
OnConnectionClosed ConnectionCallback
// 错误回调 / Error callback
OnError ErrorCallback
}
// DefaultConfig 返回默认配置
// DefaultConfig returns default configuration
func DefaultConfig() *PacketsConfig {
return &PacketsConfig{
ConnectionTimeout: DefaultConnectionTimeout,
CleanupInterval: DefaultCleanupInterval,
LazyParsing: false,
EnableDebugLog: false,
ShardCount: DefaultShardCount,
}
}
// ════════════════════════════════════════════════
// 统计信息结构体 / Statistics Structures
// ════════════════════════════════════════════════
// ErrorStats 错误统计信息
// ErrorStats error statistics
type ErrorStats struct {
LinkLayerErrors uint64 // 链路层错误数 / Link layer error count
NetworkErrors uint64 // 网络层错误数 / Network layer error count
TransportErrors uint64 // 传输层错误数 / Transport layer error count
UnsupportedErrors uint64 // 不支持协议错误数 / Unsupported protocol error count
TotalErrors uint64 // 总错误数 / Total error count
}
// ConnectionStats 连接统计信息
// ConnectionStats connection statistics
type ConnectionStats struct {
ActiveConnections int64 // 当前活跃连接数 / Current active connections
TotalConnections uint64 // 历史总连接数 / Total historical connections
ClosedConnections uint64 // 已关闭连接数 / Closed connections
TimeoutConnections uint64 // 超时清理的连接数 / Timeout cleaned connections
TcpConnections int64 // TCP 连接数 / TCP connection count
UdpConnections int64 // UDP 连接数 / UDP connection count
IcmpConnections int64 // ICMP 连接数 / ICMP connection count
}
// Stats 综合统计信息
// Stats comprehensive statistics
type Stats struct {
Errors ErrorStats // 错误统计 / Error statistics
Connections ConnectionStats // 连接统计 / Connection statistics
StartTime time.Time // 启动时间 / Start time
LastCleanup time.Time // 上次清理时间 / Last cleanup time
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
// ════════════════════════════════════════════════
// 数据包信息结构体 / Packet Info Structure
// ════════════════════════════════════════════════════════════════════════════════
// PacketInfo 数据包信息结构体,包含完整的网络层和传输层信息
// PacketInfo structure containing complete network and transport layer information
2024-11-24 11:30:27 +08:00
type PacketInfo struct {
2026-02-04 13:33:54 +08:00
Key string // 连接唯一标识 / Unique connection identifier
ReverseKey string // 反向连接标识 / Reverse connection identifier
Type string // 协议类型: tcp/udp/icmp/icmpv6 / Protocol type
SrcMac net.HardwareAddr // 源 MAC 地址 / Source MAC address
DstMac net.HardwareAddr // 目标 MAC 地址 / Destination MAC address
SrcIP string // 源 IP 地址 / Source IP address
SrcPort string // 源端口 (TCP/UDP) / Source port
DstIP string // 目标 IP 地址 / Destination IP address
DstPort string // 目标端口 (TCP/UDP) / Destination port
// 时间戳相关字段 / Timestamp related fields
Timestamp time.Time // 数据包时间戳 / Packet timestamp
TimestampMicros int64 // 微秒级时间戳 / Microsecond timestamp
RelativeTime time.Duration // 相对于首包的时间偏移 / Time offset relative to first packet
// ICMP 相关字段 / ICMP related fields
IcmpType uint8 // ICMP 类型 / ICMP type
IcmpCode uint8 // ICMP 代码 / ICMP code
IcmpChecksum uint16 // ICMP 校验和 / ICMP checksum
IcmpId uint16 // ICMP 标识符 / ICMP identifier
IcmpSeq uint16 // ICMP 序列号 / ICMP sequence number
// 连接统计字段 / Connection statistics fields
PacketCount uint64 // 该连接的数据包计数 / Packet count for this connection
ByteCount uint64 // 该连接的字节计数 / Byte count for this connection
FirstSeen time.Time // 首次出现时间 / First seen time
LastSeen time.Time // 最后出现时间 / Last seen time
// 内部状态字段 / Internal state fields
comment string // 用户自定义注释 / User-defined comment
packet gopacket.Packet // 原始数据包 / Raw packet
tcpSeq uint32 // TCP 序列号 / TCP sequence number
tcpAck uint32 // TCP 确认号 / TCP acknowledgment number
tcpWindow uint16 // TCP 窗口大小 / TCP window size
tcpPayloads int // 载荷长度 / Payload length
finState bool // TCP FIN 标志 / TCP FIN flag
synState bool // TCP SYN 标志 / TCP SYN flag
isFirst bool // 是否为首次出现 / Whether first occurrence
stateDescript uint8 // 状态描述符 / State descriptor
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
// PacketInfo 的 Getter 方法 / PacketInfo getter methods
func (p PacketInfo) StateDescript() uint8 { return p.stateDescript }
func (p PacketInfo) TcpPayloads() int { return p.tcpPayloads }
func (p PacketInfo) FinState() bool { return p.finState }
func (p PacketInfo) SynState() bool { return p.synState }
func (p PacketInfo) TcpWindow() uint16 { return p.tcpWindow }
func (p PacketInfo) TcpAck() uint32 { return p.tcpAck }
func (p PacketInfo) TcpSeq() uint32 { return p.tcpSeq }
func (p PacketInfo) Packet() gopacket.Packet { return p.packet }
func (p PacketInfo) Comment() string { return p.comment }
func (p *PacketInfo) SetComment(comment string) { p.comment = comment }
// ════════════════════════════════════════════════
// 分片 Map 实现(减少锁竞争)/ Sharded Map Implementation (reduce lock contention)
// ════════════════════════════════════════════════
// shard 单个分片
// shard single shard
type shard struct {
sync.RWMutex
items map[string]PacketInfo
}
// shardedMap 分片 Map通过将数据分散到多个分片来减少锁竞争
// shardedMap sharded map, reduces lock contention by distributing data across multiple shards
type shardedMap struct {
shards []*shard
shardCount int
}
// newShardedMap 创建新的分片 Map
// newShardedMap creates a new sharded map
func newShardedMap(shardCount int) *shardedMap {
if shardCount <= 0 {
shardCount = DefaultShardCount
}
sm := &shardedMap{
shards: make([]*shard, shardCount),
shardCount: shardCount,
}
for i := 0; i < shardCount; i++ {
sm.shards[i] = &shard{
items: make(map[string]PacketInfo),
}
}
return sm
}
// getShard 根据 key 获取对应的分片
// getShard gets the shard for a given key
func (sm *shardedMap) getShard(key string) *shard {
hash := fnvHash(key)
return sm.shards[hash%uint32(sm.shardCount)]
}
// fnvHash FNV-1a 哈希函数,用于快速计算字符串哈希
// fnvHash FNV-1a hash function for fast string hashing
func fnvHash(key string) uint32 {
hash := uint32(2166136261)
for i := 0; i < len(key); i++ {
hash ^= uint32(key[i])
hash *= 16777619
}
return hash
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
// Get 获取值 / Get value
func (sm *shardedMap) Get(key string) (PacketInfo, bool) {
shard := sm.getShard(key)
shard.RLock()
val, ok := shard.items[key]
shard.RUnlock()
return val, ok
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
// Set 设置值 / Set value
func (sm *shardedMap) Set(key string, value PacketInfo) {
shard := sm.getShard(key)
shard.Lock()
shard.items[key] = value
shard.Unlock()
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
// Delete 删除值 / Delete value
func (sm *shardedMap) Delete(key string) {
shard := sm.getShard(key)
shard.Lock()
delete(shard.items, key)
shard.Unlock()
}
// DeleteBatch 批量删除 / Batch delete
func (sm *shardedMap) DeleteBatch(keys []string) {
// 按分片分组 keys / Group keys by shard
shardKeys := make(map[int][]string)
for _, key := range keys {
hash := fnvHash(key)
shardIdx := int(hash % uint32(sm.shardCount))
shardKeys[shardIdx] = append(shardKeys[shardIdx], key)
}
// 对每个分片批量删除 / Batch delete for each shard
for shardIdx, keys := range shardKeys {
shard := sm.shards[shardIdx]
shard.Lock()
for _, key := range keys {
delete(shard.items, key)
}
shard.Unlock()
}
}
// Len 获取总长度 / Get total length
func (sm *shardedMap) Len() int {
total := 0
for _, shard := range sm.shards {
shard.RLock()
total += len(shard.items)
shard.RUnlock()
}
return total
}
// GetAll 获取所有项 / Get all items
func (sm *shardedMap) GetAll() []PacketInfo {
var result []PacketInfo
for _, shard := range sm.shards {
shard.RLock()
for _, v := range shard.items {
result = append(result, v)
}
shard.RUnlock()
}
return result
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
// Range 遍历所有项 / Range over all items
func (sm *shardedMap) Range(f func(key string, value PacketInfo) bool) {
for _, shard := range sm.shards {
shard.RLock()
for k, v := range shard.items {
if !f(k, v) {
shard.RUnlock()
return
}
}
shard.RUnlock()
}
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
// Clear 清空所有项 / Clear all items
func (sm *shardedMap) Clear() {
for _, shard := range sm.shards {
shard.Lock()
shard.items = make(map[string]PacketInfo)
shard.Unlock()
}
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
// ════════════════════════════════════════════════
// 对象池(减少内存分配)/ Object Pool (reduce memory allocation)
// ════════════════════════════════════════════════
// stringBuilderPool strings.Builder 对象池
var stringBuilderPool = sync.Pool{
New: func() interface{} {
return &strings.Builder{}
},
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
// getStringBuilder 从对象池获取 strings.Builder
// getStringBuilder gets strings.Builder from pool
func getStringBuilder() *strings.Builder {
return stringBuilderPool.Get().(*strings.Builder)
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
// putStringBuilder 将 strings.Builder 放回对象池
// putStringBuilder puts strings.Builder back to pool
func putStringBuilder(sb *strings.Builder) {
sb.Reset()
stringBuilderPool.Put(sb)
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
// buildKey 使用对象池优化的 key 构建函数
// buildKey optimized key building function using object pool
func buildKey(protocol, srcIP, srcPort, dstIP, dstPort string) string {
sb := getStringBuilder()
defer putStringBuilder(sb)
sb.WriteString(protocol)
sb.WriteString("://")
sb.WriteString(srcIP)
if srcPort != "" {
sb.WriteString(":")
sb.WriteString(srcPort)
}
sb.WriteString("=")
sb.WriteString(dstIP)
if dstPort != "" {
sb.WriteString(":")
sb.WriteString(dstPort)
}
return sb.String()
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
// ════════════════════════════════════════════════
// Packets 主结构体 / Packets Main Structure
// ════════════════════════════════════════════════
// Packets 数据包管理器,用于跟踪和解析网络数据包
// Packets manager for tracking and parsing network packets
type Packets struct {
config *PacketsConfig // 配置 / Configuration
connections *shardedMap // 连接映射表 / Connection map
stats Stats // 统计信息 / Statistics
statsLock sync.RWMutex // 统计信息锁 / Statistics lock
startTime time.Time // 启动时间 / Start time
firstPacketTime time.Time // 首个数据包时间 / First packet time
cleanupTicker *time.Ticker // 清理定时器 / Cleanup ticker
stopCleanup chan struct{} // 停止清理信号 / Stop cleanup signal
cleanupOnce sync.Once // 确保只启动一次清理 / Ensure cleanup starts only once
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
// NewPackets 创建新的数据包管理器实例(使用默认配置)
// NewPackets creates a new Packets manager instance (with default config)
2024-11-24 11:30:27 +08:00
func NewPackets() *Packets {
2026-02-04 13:33:54 +08:00
return NewPacketsWithConfig(DefaultConfig())
}
// NewPacketsWithConfig 使用自定义配置创建数据包管理器
// NewPacketsWithConfig creates Packets manager with custom config
func NewPacketsWithConfig(config *PacketsConfig) *Packets {
if config == nil {
config = DefaultConfig()
}
p := &Packets{
config: config,
connections: newShardedMap(config.ShardCount),
startTime: time.Now(),
stopCleanup: make(chan struct{}),
}
p.stats.StartTime = p.startTime
// 启动自动清理 goroutine / Start auto cleanup goroutine
if config.CleanupInterval > 0 {
p.startAutoCleanup()
}
return p
}
// startAutoCleanup 启动自动清理 goroutine
// startAutoCleanup starts auto cleanup goroutine
func (p *Packets) startAutoCleanup() {
p.cleanupOnce.Do(func() {
p.cleanupTicker = time.NewTicker(p.config.CleanupInterval)
go func() {
for {
select {
case <-p.cleanupTicker.C:
p.CleanupExpiredConnections()
case <-p.stopCleanup:
p.cleanupTicker.Stop()
return
}
}
}()
})
}
// Stop 停止数据包管理器(停止自动清理)
// Stop stops the packets manager (stops auto cleanup)
func (p *Packets) Stop() {
close(p.stopCleanup)
}
// ════════════════════════════════════════════════
// 统计和查询方法 / Statistics and Query Methods
// ════════════════════════════════════════════════
// GetStats 获取统计信息
// GetStats gets statistics
func (p *Packets) GetStats() Stats {
p.statsLock.RLock()
defer p.statsLock.RUnlock()
stats := p.stats
stats.Connections.ActiveConnections = int64(p.connections.Len())
return stats
}
// GetConnectionCount 获取当前活跃连接数
// GetConnectionCount gets current active connection count
func (p *Packets) GetConnectionCount() int {
return p.connections.Len()
}
// GetAllConnections 获取所有活跃连接
// GetAllConnections gets all active connections
func (p *Packets) GetAllConnections() []PacketInfo {
return p.connections.GetAll()
}
// GetConnectionsByIP 根据 IP 地址查询连接
// GetConnectionsByIP queries connections by IP address
func (p *Packets) GetConnectionsByIP(ip string) []PacketInfo {
var result []PacketInfo
p.connections.Range(func(key string, value PacketInfo) bool {
if value.SrcIP == ip || value.DstIP == ip {
result = append(result, value)
}
return true
})
return result
}
// GetConnectionsByPort 根据端口查询连接
// GetConnectionsByPort queries connections by port
func (p *Packets) GetConnectionsByPort(port string) []PacketInfo {
var result []PacketInfo
p.connections.Range(func(key string, value PacketInfo) bool {
if value.SrcPort == port || value.DstPort == port {
result = append(result, value)
}
return true
})
return result
}
// GetConnectionsByType 根据协议类型查询连接
// GetConnectionsByType queries connections by protocol type
func (p *Packets) GetConnectionsByType(protocolType string) []PacketInfo {
var result []PacketInfo
p.connections.Range(func(key string, value PacketInfo) bool {
if value.Type == protocolType {
result = append(result, value)
}
return true
})
return result
}
// Key 根据 key 获取连接信息
// Key gets connection info by key
func (p *Packets) Key(key string) (PacketInfo, bool) {
return p.connections.Get(key)
}
// SetComment 设置连接注释
// SetComment sets connection comment
func (p *Packets) SetComment(key, comment string) {
if info, ok := p.connections.Get(key); ok {
info.comment = comment
p.connections.Set(key, info)
}
}
// ════════════════════════════════════════════════
// 连接清理方法 / Connection Cleanup Methods
// ════════════════════════════════════════════════
// CleanupExpiredConnections 清理过期连接
// CleanupExpiredConnections cleans up expired connections
func (p *Packets) CleanupExpiredConnections() int {
now := time.Now()
timeout := p.config.ConnectionTimeout
var expiredKeys []string
// 收集过期的 keys / Collect expired keys
p.connections.Range(func(key string, value PacketInfo) bool {
if now.Sub(value.LastSeen) > timeout {
expiredKeys = append(expiredKeys, key)
}
return true
})
// 批量删除 / Batch delete
if len(expiredKeys) > 0 {
p.connections.DeleteBatch(expiredKeys)
// 更新统计 / Update statistics
p.statsLock.Lock()
p.stats.Connections.TimeoutConnections += uint64(len(expiredKeys))
p.stats.LastCleanup = now
p.statsLock.Unlock()
}
return len(expiredKeys)
}
// ClearAllConnections 清空所有连接
// ClearAllConnections clears all connections
func (p *Packets) ClearAllConnections() {
p.connections.Clear()
p.statsLock.Lock()
p.stats.Connections.ActiveConnections = 0
p.statsLock.Unlock()
}
// ════════════════════════════════════════════════
// 错误处理方法 / Error Handling Methods
// ════════════════════════════════════════════════
// recordError 记录错误统计
// recordError records error statistics
func (p *Packets) recordError(errType ParseErrorType) {
p.statsLock.Lock()
defer p.statsLock.Unlock()
p.stats.Errors.TotalErrors++
switch errType {
case ErrTypeLinkLayer:
p.stats.Errors.LinkLayerErrors++
case ErrTypeNetwork:
p.stats.Errors.NetworkErrors++
case ErrTypeTransport:
p.stats.Errors.TransportErrors++
case ErrTypeUnsupported:
p.stats.Errors.UnsupportedErrors++
2024-11-24 11:30:27 +08:00
}
}
2026-02-04 13:33:54 +08:00
// handleError 处理错误(记录统计并调用回调)
// handleError handles error (records statistics and calls callback)
func (p *Packets) handleError(parseErr *ParseError, packet gopacket.Packet) {
p.recordError(parseErr.Type)
if p.config.EnableDebugLog {
fmt.Printf("[ERROR] %s\n", parseErr.Error())
}
if p.config.OnError != nil {
p.config.OnError(parseErr, packet)
}
}
// ════════════════════════════════════════════════
// 数据包解析方法 / Packet Parsing Methods
// ════════════════════════════════════════════════
// ParsePacket 解析数据包,支持 Ethernet、Linux SLL、Linux SLL2 等链路层格式
// ParsePacket parses packets, supporting Ethernet, Linux SLL, Linux SLL2 and other link layer formats
//
// 参数 / Parameters:
// - packet: gopacket 数据包对象 / gopacket packet object
// - opts: 可选参数opts[0] 可以是 *[]byte 类型的 MAC 地址(用于 nfqueue 等场景)
// / Optional parameters, opts[0] can be *[]byte type MAC address (for nfqueue scenarios)
//
// 返回 / Returns:
// - PacketInfo: 解析后的数据包信息 / Parsed packet information
// - error: 解析错误 / Parse error
2024-11-24 11:30:27 +08:00
func (p *Packets) ParsePacket(packet gopacket.Packet, opts ...interface{}) (PacketInfo, error) {
var info PacketInfo
2026-02-04 13:33:54 +08:00
// 提取时间戳 / Extract timestamp
metadata := packet.Metadata()
if metadata != nil {
info.Timestamp = metadata.Timestamp
info.TimestampMicros = metadata.Timestamp.UnixMicro()
// 记录首个数据包时间 / Record first packet time
if p.firstPacketTime.IsZero() {
p.firstPacketTime = metadata.Timestamp
}
// 计算相对时间 / Calculate relative time
info.RelativeTime = metadata.Timestamp.Sub(p.firstPacketTime)
} else {
info.Timestamp = time.Now()
info.TimestampMicros = info.Timestamp.UnixMicro()
}
// ────────────────────────────────────────────────
// 链路层:提取 MAC 地址 / Link Layer: Extract MAC addresses
// 支持 Ethernet、Linux SLL、Linux SLL2 / Support Ethernet, Linux SLL, Linux SLL2
// ────────────────────────────────────────────────
var srcMac, dstMac net.HardwareAddr
// 情况 1: 标准以太网层 / Case 1: Standard Ethernet layer
if ethLayer := packet.Layer(layers.LayerTypeEthernet); ethLayer != nil {
eth := ethLayer.(*layers.Ethernet)
srcMac = eth.SrcMAC
dstMac = eth.DstMAC
} else if sllLayer := packet.Layer(layers.LayerTypeLinuxSLL); sllLayer != nil {
// 情况 2: Linux SLL (cooked capture v1) / Case 2: Linux SLL (cooked capture v1)
sll := sllLayer.(*layers.LinuxSLL)
if sll.AddrType == 1 && sll.AddrLen == 6 { // 1 = ARPHRD_ETHER
srcMac = sll.Addr
}
} else if sll2Layer := packet.Layer(layers.LayerTypeLinuxSLL2); sll2Layer != nil {
// 情况 3: Linux SLL2 (cooked capture v2) / Case 3: Linux SLL2 (cooked capture v2)
sll2 := sll2Layer.(*layers.LinuxSLL2)
if sll2.ARPHardwareType == 1 && sll2.AddrLength == 6 { // 1 = ARPHRD_ETHER
srcMac = sll2.Addr
}
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
// 可选:使用外部提供的 MAC 地址覆盖 / Optional: Override with externally provided MAC
2024-11-24 11:30:27 +08:00
for k, v := range opts {
2026-02-04 13:33:54 +08:00
if k == 0 {
if b, ok := v.(*[]byte); ok && b != nil && len(*b) == 6 {
srcMac = net.HardwareAddr(*b)
2024-11-24 11:30:27 +08:00
}
}
}
2026-02-04 13:33:54 +08:00
info.SrcMac = srcMac
info.DstMac = dstMac
// ────────────────────────────────────────────────
// 网络层:提取 IP 地址 / Network Layer: Extract IP addresses
// ────────────────────────────────────────────────
2024-11-24 11:30:27 +08:00
if nw := packet.NetworkLayer(); nw != nil {
srcp, dstp := nw.NetworkFlow().Endpoints()
info.SrcIP = srcp.String()
info.DstIP = dstp.String()
} else {
2026-02-04 13:33:54 +08:00
parseErr := NewParseError(ErrTypeNetwork, "Network", "no valid network layer found", nil)
p.handleError(parseErr, packet)
return info, parseErr
}
// ────────────────────────────────────────────────
// 传输层:解析 TCP/UDP/ICMP / Transport Layer: Parse TCP/UDP/ICMP
// ────────────────────────────────────────────────
// TCP 协议 / TCP protocol
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
if tcp, ok := tcpLayer.(*layers.TCP); ok {
return p.parseTcp(info, packet, tcpLayer, tcp)
2024-11-24 11:30:27 +08:00
}
}
2026-02-04 13:33:54 +08:00
// UDP 协议 / UDP protocol
if udpLayer := packet.Layer(layers.LayerTypeUDP); udpLayer != nil {
if udp, ok := udpLayer.(*layers.UDP); ok {
return p.parseUdp(info, packet, udpLayer, udp)
}
}
// ICMPv4 协议 / ICMPv4 protocol
if icmpLayer := packet.Layer(layers.LayerTypeICMPv4); icmpLayer != nil {
if icmp, ok := icmpLayer.(*layers.ICMPv4); ok {
return p.parseIcmp(info, packet, icmpLayer, icmp)
2024-11-24 11:30:27 +08:00
}
}
2026-02-04 13:33:54 +08:00
// ICMPv6 协议 / ICMPv6 protocol
if icmpv6Layer := packet.Layer(layers.LayerTypeICMPv6); icmpv6Layer != nil {
if icmpv6, ok := icmpv6Layer.(*layers.ICMPv6); ok {
return p.parseIcmpv6(info, packet, icmpv6Layer, icmpv6)
}
}
// 不支持的协议类型 / Unsupported protocol type
parseErr := NewParseError(ErrTypeUnsupported, "Transport",
"unsupported packet type (not TCP/UDP/ICMP/ICMPv6)", nil)
p.handleError(parseErr, packet)
return info, parseErr
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
// parseTcp 解析 TCP 数据包并进行状态跟踪
// parseTcp parses TCP packets and performs state tracking
2024-11-24 11:30:27 +08:00
func (p *Packets) parseTcp(info PacketInfo, packet gopacket.Packet, layer gopacket.Layer, tcp *layers.TCP) (PacketInfo, error) {
2026-02-04 13:33:54 +08:00
// 使用优化的 key 构建 / Use optimized key building
info.Key = buildKey("tcp", info.SrcIP, fmt.Sprintf("%d", tcp.SrcPort), info.DstIP, fmt.Sprintf("%d", tcp.DstPort))
info.ReverseKey = buildKey("tcp", info.DstIP, fmt.Sprintf("%d", tcp.DstPort), info.SrcIP, fmt.Sprintf("%d", tcp.SrcPort))
2024-11-24 11:30:27 +08:00
info.Type = "tcp"
info.SrcPort = fmt.Sprintf("%d", tcp.SrcPort)
info.DstPort = fmt.Sprintf("%d", tcp.DstPort)
info.packet = packet
info.tcpSeq = tcp.Seq
info.tcpAck = tcp.Ack
info.tcpPayloads = len(layer.LayerPayload())
info.finState = tcp.FIN
info.synState = tcp.SYN
info.tcpWindow = tcp.Window
2026-02-04 13:33:54 +08:00
// 获取上一个同方向的数据包 / Get the last packet in the same direction
lastPacket, exists := p.connections.Get(info.Key)
// 如果是新连接,初始化状态 / If it's a new connection, initialize state
if !exists {
2024-11-24 11:30:27 +08:00
lastPacket = PacketInfo{
Key: info.Key,
ReverseKey: info.ReverseKey,
Type: "tcp",
SrcIP: info.SrcIP,
SrcPort: info.SrcPort,
DstIP: info.DstIP,
DstPort: info.DstPort,
2026-02-04 13:33:54 +08:00
FirstSeen: info.Timestamp,
LastSeen: info.Timestamp,
PacketCount: 0,
ByteCount: 0,
2024-11-24 11:30:27 +08:00
tcpSeq: tcp.Seq,
tcpAck: tcp.Ack,
tcpWindow: tcp.Window,
tcpPayloads: len(layer.LayerPayload()),
finState: tcp.FIN,
synState: tcp.SYN,
isFirst: true,
2026-02-04 13:33:54 +08:00
stateDescript: StateUnknown,
}
// 更新统计 / Update statistics
p.statsLock.Lock()
p.stats.Connections.TotalConnections++
atomic.AddInt64(&p.stats.Connections.TcpConnections, 1)
p.statsLock.Unlock()
// 触发新连接回调 / Trigger new connection callback
if p.config.OnNewConnection != nil {
p.config.OnNewConnection(lastPacket)
2024-11-24 11:30:27 +08:00
}
}
2026-02-04 13:33:54 +08:00
// 更新连接统计 / Update connection statistics
info.FirstSeen = lastPacket.FirstSeen
info.LastSeen = info.Timestamp
info.PacketCount = lastPacket.PacketCount + 1
info.ByteCount = lastPacket.ByteCount + uint64(len(packet.Data()))
// 获取反向连接的数据包 / Get the reverse direction packet
lastReverse, _ := p.connections.Get(info.ReverseKey)
// 继承上一个数据包的注释和 MAC 地址 / Inherit comment and MAC addresses from last packet
2024-11-24 11:30:27 +08:00
if !lastPacket.isFirst {
info.comment = lastPacket.comment
if lastPacket.SrcMac != nil && len(info.SrcMac) == 0 {
info.SrcMac = lastPacket.SrcMac
}
2026-02-04 13:33:54 +08:00
if lastPacket.DstMac != nil && len(info.DstMac) == 0 {
info.DstMac = lastPacket.DstMac
2024-11-24 11:30:27 +08:00
}
}
if lastReverse.SrcMac != nil && len(info.DstMac) == 0 {
info.DstMac = lastReverse.SrcMac
}
2026-02-04 13:33:54 +08:00
// ────────────────────────────────────────────────
// TCP 状态机判断 / TCP state machine
// ────────────────────────────────────────────────
connectionClosed := false
// RST 标志:连接重置 / RST flag: connection reset
if tcp.RST {
info.stateDescript = StateTcpRst
p.connections.Delete(info.Key)
p.connections.Delete(info.ReverseKey)
connectionClosed = true
// 更新统计 / Update statistics
p.statsLock.Lock()
p.stats.Connections.ClosedConnections++
atomic.AddInt64(&p.stats.Connections.TcpConnections, -1)
p.statsLock.Unlock()
// 触发连接关闭回调 / Trigger connection closed callback
if p.config.OnConnectionClosed != nil {
p.config.OnConnectionClosed(info)
}
return info, nil
}
// 三次握手 / Three-way handshake
if tcp.SYN && !tcp.ACK {
info.stateDescript = StateTcpConnect1 // SYN
} else if tcp.SYN && tcp.ACK {
info.stateDescript = StateTcpConnect2 // SYN-ACK
} else if tcp.ACK {
if !tcp.FIN {
// 三次握手第三步 / Three-way handshake step 3
if lastReverse.tcpSeq+1 == tcp.Ack && lastReverse.stateDescript == StateTcpConnect2 {
info.stateDescript = StateTcpConnect3
} else if tcp.CWR {
info.stateDescript = StateTcpCwr
} else if tcp.ECE {
info.stateDescript = StateTcpEce
}
if info.stateDescript != StateUnknown {
goto savereturn
}
// TCP 保活检测 / TCP keepalive detection
if info.tcpSeq == lastReverse.tcpAck-1 && info.tcpSeq == lastPacket.tcpSeq+uint32(lastPacket.tcpPayloads)-1 {
info.stateDescript = StateTcpKeepalive
goto savereturn
}
// TCP 重传检测 / TCP retransmission detection
if !lastPacket.isFirst {
if info.tcpSeq < lastPacket.tcpSeq+uint32(lastPacket.tcpPayloads) {
info.stateDescript = StateTcpRetransmit
2024-11-24 11:30:27 +08:00
goto savereturn
}
2026-02-04 13:33:54 +08:00
}
// 四次挥手完成 / Four-way handshake completed
if lastReverse.finState && lastPacket.finState {
info.stateDescript = StateTcpDisconnect4
p.connections.Delete(info.Key)
p.connections.Delete(info.ReverseKey)
connectionClosed = true
// 更新统计 / Update statistics
p.statsLock.Lock()
p.stats.Connections.ClosedConnections++
atomic.AddInt64(&p.stats.Connections.TcpConnections, -1)
p.statsLock.Unlock()
// 触发连接关闭回调 / Trigger connection closed callback
if p.config.OnConnectionClosed != nil {
p.config.OnConnectionClosed(info)
2024-11-24 11:30:27 +08:00
}
2026-02-04 13:33:54 +08:00
return info, nil
}
// 四次挥手第二步 / Four-way handshake step 2
if lastReverse.finState && lastReverse.tcpSeq+1 == info.tcpAck {
info.stateDescript = StateTcpDisconnect2
goto savereturn
}
// 正常 ACK / Normal ACK
info.stateDescript = StateTcpAckOk
} else {
// 四次挥手 / Four-way handshake
if !lastReverse.finState {
info.stateDescript = StateTcpDisconnect1 // FIN
2024-11-24 11:30:27 +08:00
} else {
2026-02-04 13:33:54 +08:00
if lastReverse.finState && lastReverse.tcpSeq+1 == info.tcpAck &&
lastPacket.tcpAck == info.tcpAck && lastPacket.tcpSeq == info.tcpSeq {
info.stateDescript = StateTcpDisconnect3 // FIN (step 3)
2024-11-24 11:30:27 +08:00
} else {
2026-02-04 13:33:54 +08:00
info.stateDescript = StateTcpDisconnect23 // FIN-ACK (step 2+3 combined)
2024-11-24 11:30:27 +08:00
}
}
}
}
2026-02-04 13:33:54 +08:00
2024-11-24 11:30:27 +08:00
savereturn:
2026-02-04 13:33:54 +08:00
// 只有在连接未关闭时才保存 / Only save if connection is not closed
if !connectionClosed {
p.connections.Set(info.Key, info)
}
2024-11-24 11:30:27 +08:00
return info, nil
}
2026-02-04 13:33:54 +08:00
// parseUdp 解析 UDP 数据包
// parseUdp parses UDP packets
2024-11-24 11:30:27 +08:00
func (p *Packets) parseUdp(info PacketInfo, packet gopacket.Packet, layer gopacket.Layer, udp *layers.UDP) (PacketInfo, error) {
2026-02-04 13:33:54 +08:00
// 使用优化的 key 构建 / Use optimized key building
info.Key = buildKey("udp", info.SrcIP, fmt.Sprintf("%d", udp.SrcPort), info.DstIP, fmt.Sprintf("%d", udp.DstPort))
info.ReverseKey = buildKey("udp", info.DstIP, fmt.Sprintf("%d", udp.DstPort), info.SrcIP, fmt.Sprintf("%d", udp.SrcPort))
2024-11-24 11:30:27 +08:00
info.Type = "udp"
info.SrcPort = fmt.Sprintf("%d", udp.SrcPort)
info.DstPort = fmt.Sprintf("%d", udp.DstPort)
info.packet = packet
info.tcpPayloads = len(layer.LayerPayload())
2026-02-04 13:33:54 +08:00
info.stateDescript = StateUdp
// 获取已存在的连接信息 / Get existing connection info
lastPacket, exists := p.connections.Get(info.Key)
if !exists {
// 新 UDP 连接 / New UDP connection
info.FirstSeen = info.Timestamp
info.LastSeen = info.Timestamp
info.PacketCount = 1
info.ByteCount = uint64(len(packet.Data()))
// 更新统计 / Update statistics
p.statsLock.Lock()
p.stats.Connections.TotalConnections++
atomic.AddInt64(&p.stats.Connections.UdpConnections, 1)
p.statsLock.Unlock()
// 触发新连接回调 / Trigger new connection callback
if p.config.OnNewConnection != nil {
p.config.OnNewConnection(info)
}
} else {
// 更新已存在的连接 / Update existing connection
info.FirstSeen = lastPacket.FirstSeen
info.LastSeen = info.Timestamp
info.PacketCount = lastPacket.PacketCount + 1
info.ByteCount = lastPacket.ByteCount + uint64(len(packet.Data()))
info.comment = lastPacket.comment
// 继承 MAC 地址 / Inherit MAC addresses
if lastPacket.SrcMac != nil && len(info.SrcMac) == 0 {
info.SrcMac = lastPacket.SrcMac
}
if lastPacket.DstMac != nil && len(info.DstMac) == 0 {
info.DstMac = lastPacket.DstMac
}
}
p.connections.Set(info.Key, info)
return info, nil
}
// parseIcmp 解析 ICMPv4 数据包
// parseIcmp parses ICMPv4 packets
func (p *Packets) parseIcmp(info PacketInfo, packet gopacket.Packet, layer gopacket.Layer, icmp *layers.ICMPv4) (PacketInfo, error) {
info.Type = "icmp"
info.IcmpType = uint8(icmp.TypeCode.Type())
info.IcmpCode = uint8(icmp.TypeCode.Code())
info.IcmpChecksum = icmp.Checksum
info.IcmpId = icmp.Id
info.IcmpSeq = icmp.Seq
info.tcpPayloads = len(layer.LayerPayload())
info.stateDescript = StateIcmp
// ICMP 的 Key 格式icmp://srcIP=dstIP:type:code:id:seq
// ICMP Key format: icmp://srcIP=dstIP:type:code:id:seq
sb := getStringBuilder()
defer putStringBuilder(sb)
sb.WriteString("icmp://")
sb.WriteString(info.SrcIP)
sb.WriteString("=")
sb.WriteString(info.DstIP)
sb.WriteString(":")
sb.WriteString(fmt.Sprintf("%d:%d:%d:%d", info.IcmpType, info.IcmpCode, info.IcmpId, info.IcmpSeq))
info.Key = sb.String()
sb.Reset()
sb.WriteString("icmp://")
sb.WriteString(info.DstIP)
sb.WriteString("=")
sb.WriteString(info.SrcIP)
sb.WriteString(":")
sb.WriteString(fmt.Sprintf("%d:%d:%d:%d", info.IcmpType, info.IcmpCode, info.IcmpId, info.IcmpSeq))
info.ReverseKey = sb.String()
info.packet = packet
// 获取已存在的连接信息 / Get existing connection info
lastPacket, exists := p.connections.Get(info.Key)
if !exists {
// 新 ICMP 连接 / New ICMP connection
info.FirstSeen = info.Timestamp
info.LastSeen = info.Timestamp
info.PacketCount = 1
info.ByteCount = uint64(len(packet.Data()))
// 更新统计 / Update statistics
p.statsLock.Lock()
p.stats.Connections.TotalConnections++
atomic.AddInt64(&p.stats.Connections.IcmpConnections, 1)
p.statsLock.Unlock()
// 触发新连接回调 / Trigger new connection callback
if p.config.OnNewConnection != nil {
p.config.OnNewConnection(info)
}
} else {
// 更新已存在的连接 / Update existing connection
info.FirstSeen = lastPacket.FirstSeen
info.LastSeen = info.Timestamp
info.PacketCount = lastPacket.PacketCount + 1
info.ByteCount = lastPacket.ByteCount + uint64(len(packet.Data()))
info.comment = lastPacket.comment
// 继承 MAC 地址 / Inherit MAC addresses
if lastPacket.SrcMac != nil && len(info.SrcMac) == 0 {
info.SrcMac = lastPacket.SrcMac
}
if lastPacket.DstMac != nil && len(info.DstMac) == 0 {
info.DstMac = lastPacket.DstMac
}
}
p.connections.Set(info.Key, info)
2024-11-24 11:30:27 +08:00
return info, nil
}
2026-02-04 13:33:54 +08:00
// parseIcmpv6 解析 ICMPv6 数据包
// parseIcmpv6 parses ICMPv6 packets
func (p *Packets) parseIcmpv6(info PacketInfo, packet gopacket.Packet, layer gopacket.Layer, icmpv6 *layers.ICMPv6) (PacketInfo, error) {
info.Type = "icmpv6"
info.IcmpType = uint8(icmpv6.TypeCode.Type())
info.IcmpCode = uint8(icmpv6.TypeCode.Code())
info.IcmpChecksum = icmpv6.Checksum
info.tcpPayloads = len(layer.LayerPayload())
info.stateDescript = StateIcmpv6
// ICMPv6 的 Key 格式icmpv6://srcIP=dstIP:type:code
// ICMPv6 Key format: icmpv6://srcIP=dstIP:type:code
sb := getStringBuilder()
defer putStringBuilder(sb)
sb.WriteString("icmpv6://")
sb.WriteString(info.SrcIP)
sb.WriteString("=")
sb.WriteString(info.DstIP)
sb.WriteString(":")
sb.WriteString(fmt.Sprintf("%d:%d", info.IcmpType, info.IcmpCode))
info.Key = sb.String()
sb.Reset()
sb.WriteString("icmpv6://")
sb.WriteString(info.DstIP)
sb.WriteString("=")
sb.WriteString(info.SrcIP)
sb.WriteString(":")
sb.WriteString(fmt.Sprintf("%d:%d", info.IcmpType, info.IcmpCode))
info.ReverseKey = sb.String()
info.packet = packet
// 获取已存在的连接信息 / Get existing connection info
lastPacket, exists := p.connections.Get(info.Key)
if !exists {
// 新 ICMPv6 连接 / New ICMPv6 connection
info.FirstSeen = info.Timestamp
info.LastSeen = info.Timestamp
info.PacketCount = 1
info.ByteCount = uint64(len(packet.Data()))
// 更新统计 / Update statistics
p.statsLock.Lock()
p.stats.Connections.TotalConnections++
atomic.AddInt64(&p.stats.Connections.IcmpConnections, 1)
p.statsLock.Unlock()
// 触发新连接回调 / Trigger new connection callback
if p.config.OnNewConnection != nil {
p.config.OnNewConnection(info)
}
} else {
// 更新已存在的连接 / Update existing connection
info.FirstSeen = lastPacket.FirstSeen
info.LastSeen = info.Timestamp
info.PacketCount = lastPacket.PacketCount + 1
info.ByteCount = lastPacket.ByteCount + uint64(len(packet.Data()))
info.comment = lastPacket.comment
// 继承 MAC 地址 / Inherit MAC addresses
if lastPacket.SrcMac != nil && len(info.SrcMac) == 0 {
info.SrcMac = lastPacket.SrcMac
}
if lastPacket.DstMac != nil && len(info.DstMac) == 0 {
info.DstMac = lastPacket.DstMac
}
}
p.connections.Set(info.Key, info)
return info, nil
}
// ════════════════════════════════════════════════
// 辅助方法和工具函数 / Helper Methods and Utility Functions
// ════════════════════════════════════════════════
// GetStateDescription 获取状态描述符的文本描述
// GetStateDescription gets text description of state descriptor
func GetStateDescription(state uint8) string {
switch state {
case StateUnknown:
return "Unknown"
case StateTcpConnect1:
return "TCP SYN"
case StateTcpConnect2:
return "TCP SYN-ACK"
case StateTcpConnect3:
return "TCP ACK (Connected)"
case StateTcpDisconnect1:
return "TCP FIN (Step 1)"
case StateTcpDisconnect2:
return "TCP ACK (Step 2)"
case StateTcpDisconnect23:
return "TCP FIN-ACK (Step 2+3)"
case StateTcpDisconnect3:
return "TCP FIN (Step 3)"
case StateTcpDisconnect4:
return "TCP ACK (Closed)"
case StateTcpAckOk:
return "TCP ACK"
case StateTcpRetransmit:
return "TCP Retransmission"
case StateTcpEce:
return "TCP ECE"
case StateTcpCwr:
return "TCP CWR"
case StateTcpRst:
return "TCP RST"
case StateTcpKeepalive:
return "TCP Keepalive"
case StateUdp:
return "UDP"
case StateIcmp:
return "ICMP"
case StateIcmpv6:
return "ICMPv6"
default:
return fmt.Sprintf("Unknown(%d)", state)
}
}
// FormatDuration 格式化时间间隔为人类可读格式
// FormatDuration formats duration to human readable format
func FormatDuration(d time.Duration) string {
if d < time.Microsecond {
return fmt.Sprintf("%dns", d.Nanoseconds())
} else if d < time.Millisecond {
return fmt.Sprintf("%.2fµs", float64(d.Nanoseconds())/1000.0)
} else if d < time.Second {
return fmt.Sprintf("%.2fms", float64(d.Microseconds())/1000.0)
} else if d < time.Minute {
return fmt.Sprintf("%.2fs", d.Seconds())
} else if d < time.Hour {
return fmt.Sprintf("%.2fm", d.Minutes())
}
return fmt.Sprintf("%.2fh", d.Hours())
}
// FormatBytes 格式化字节数为人类可读格式
// FormatBytes formats bytes to human readable format
func FormatBytes(bytes uint64) string {
const unit = 1024
if bytes < unit {
return fmt.Sprintf("%d B", bytes)
}
div, exp := uint64(unit), 0
for n := bytes / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.2f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
}
// PrintStats 打印统计信息(用于调试)
// PrintStats prints statistics (for debugging)
func (p *Packets) PrintStats() {
stats := p.GetStats()
fmt.Println("════════════════════════════════════════")
fmt.Println("Packet Statistics / 数据包统计")
fmt.Println("════════════════════════════════════════")
fmt.Printf("Start Time / 启动时间: %s\n", stats.StartTime.Format("2006-01-02 15:04:05"))
fmt.Printf("Uptime / 运行时间: %s\n", FormatDuration(time.Since(stats.StartTime)))
fmt.Println()
fmt.Println("Connection Statistics / 连接统计:")
fmt.Printf(" Active / 活跃: %d\n", stats.Connections.ActiveConnections)
fmt.Printf(" Total / 总计: %d\n", stats.Connections.TotalConnections)
fmt.Printf(" Closed / 已关闭: %d\n", stats.Connections.ClosedConnections)
fmt.Printf(" Timeout / 超时: %d\n", stats.Connections.TimeoutConnections)
fmt.Printf(" TCP: %d\n", stats.Connections.TcpConnections)
fmt.Printf(" UDP: %d\n", stats.Connections.UdpConnections)
fmt.Printf(" ICMP: %d\n", stats.Connections.IcmpConnections)
fmt.Println()
fmt.Println("Error Statistics / 错误统计:")
fmt.Printf(" Total / 总计: %d\n", stats.Errors.TotalErrors)
fmt.Printf(" Link Layer / 链路层: %d\n", stats.Errors.LinkLayerErrors)
fmt.Printf(" Network / 网络层: %d\n", stats.Errors.NetworkErrors)
fmt.Printf(" Transport / 传输层: %d\n", stats.Errors.TransportErrors)
fmt.Printf(" Unsupported / 不支持: %d\n", stats.Errors.UnsupportedErrors)
if !stats.LastCleanup.IsZero() {
fmt.Println()
fmt.Printf("Last Cleanup / 上次清理: %s\n", stats.LastCleanup.Format("2006-01-02 15:04:05"))
}
fmt.Println("════════════════════════════════════════")
}
// ExportConnectionsToJSON 导出连接信息为 JSON 格式(示例)
// ExportConnectionsToJSON exports connections to JSON format (example)
func (p *Packets) ExportConnectionsToJSON() string {
connections := p.GetAllConnections()
sb := getStringBuilder()
defer putStringBuilder(sb)
sb.WriteString("[\n")
for i, conn := range connections {
if i > 0 {
sb.WriteString(",\n")
}
sb.WriteString(fmt.Sprintf(` {
"key": "%s",
"type": "%s",
"src_ip": "%s",
"src_port": "%s",
"dst_ip": "%s",
"dst_port": "%s",
"packet_count": %d,
"byte_count": %d,
"state": "%s",
"first_seen": "%s",
"last_seen": "%s",
"duration": "%s"
}`,
conn.Key,
conn.Type,
conn.SrcIP,
conn.SrcPort,
conn.DstIP,
conn.DstPort,
conn.PacketCount,
conn.ByteCount,
GetStateDescription(conn.stateDescript),
conn.FirstSeen.Format(time.RFC3339),
conn.LastSeen.Format(time.RFC3339),
FormatDuration(conn.LastSeen.Sub(conn.FirstSeen)),
))
}
sb.WriteString("\n]")
return sb.String()
}