Files
Xray-core/app/stats/online_map.go
T

100 lines
1.9 KiB
Go
Raw Normal View History

2024-11-03 17:44:15 +04:00
package stats
import (
"sync"
2026-03-07 13:56:11 +03:00
"sync/atomic"
2024-11-03 17:44:15 +04:00
"time"
)
2026-03-07 13:56:11 +03:00
const (
localhostIPv4 = "127.0.0.1"
localhostIPv6 = "[::1]"
)
type ipEntry struct {
refCount int
lastSeen time.Time
}
// OnlineMap is a refcount-based implementation of stats.OnlineMap.
// IPs are tracked by reference counting: AddIP increments, RemoveIP decrements.
// An IP is removed from the map when its reference count reaches zero.
2024-11-03 17:44:15 +04:00
type OnlineMap struct {
2026-03-07 13:56:11 +03:00
entries map[string]*ipEntry
access sync.Mutex
count atomic.Int64
2024-11-03 17:44:15 +04:00
}
2026-03-07 13:56:11 +03:00
// NewOnlineMap creates a new OnlineMap instance.
2024-11-03 17:44:15 +04:00
func NewOnlineMap() *OnlineMap {
return &OnlineMap{
2026-03-07 13:56:11 +03:00
entries: make(map[string]*ipEntry),
2024-11-03 17:44:15 +04:00
}
}
// AddIP implements stats.OnlineMap.
2026-03-07 13:56:11 +03:00
func (om *OnlineMap) AddIP(ip string) {
if ip == localhostIPv4 || ip == localhostIPv6 {
2024-11-03 17:44:15 +04:00
return
}
2026-03-07 13:56:11 +03:00
om.access.Lock()
defer om.access.Unlock()
2026-03-07 13:56:11 +03:00
if e, ok := om.entries[ip]; ok {
e.refCount++
e.lastSeen = time.Now()
} else {
om.entries[ip] = &ipEntry{
refCount: 1,
lastSeen: time.Now(),
}
om.count.Add(1)
2024-11-03 17:44:15 +04:00
}
}
2026-03-07 13:56:11 +03:00
// RemoveIP implements stats.OnlineMap.
func (om *OnlineMap) RemoveIP(ip string) {
om.access.Lock()
defer om.access.Unlock()
2024-11-03 17:44:15 +04:00
2026-03-07 13:56:11 +03:00
e, ok := om.entries[ip]
if !ok {
return
}
e.refCount--
if e.refCount <= 0 {
delete(om.entries, ip)
om.count.Add(-1)
2024-11-03 17:44:15 +04:00
}
}
2026-03-07 13:56:11 +03:00
// Count implements stats.OnlineMap.
func (om *OnlineMap) Count() int {
return int(om.count.Load())
}
2024-11-03 17:44:15 +04:00
2026-03-07 13:56:11 +03:00
// List implements stats.OnlineMap.
func (om *OnlineMap) List() []string {
om.access.Lock()
defer om.access.Unlock()
keys := make([]string, 0, len(om.entries))
for ip := range om.entries {
keys = append(keys, ip)
2024-11-03 17:44:15 +04:00
}
2026-03-07 13:56:11 +03:00
return keys
2024-11-03 17:44:15 +04:00
}
2026-03-07 13:56:11 +03:00
// IPTimeMap implements stats.OnlineMap.
func (om *OnlineMap) IPTimeMap() map[string]time.Time {
om.access.Lock()
defer om.access.Unlock()
2026-03-07 13:56:11 +03:00
result := make(map[string]time.Time, len(om.entries))
for ip, e := range om.entries {
result[ip] = e.lastSeen
}
return result
}