123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- package trafficontrol
- import (
- "runtime"
- "sync"
- "sync/atomic"
- "time"
- "github.com/sagernet/sing-box/common/compatible"
- C "github.com/sagernet/sing-box/constant"
- "github.com/sagernet/sing/common"
- "github.com/sagernet/sing/common/json"
- "github.com/sagernet/sing/common/x/list"
- "github.com/gofrs/uuid/v5"
- )
- type Manager struct {
- uploadTotal atomic.Int64
- downloadTotal atomic.Int64
- connections compatible.Map[uuid.UUID, Tracker]
- closedConnectionsAccess sync.Mutex
- closedConnections list.List[TrackerMetadata]
- // process *process.Process
- memory uint64
- }
- func NewManager() *Manager {
- return &Manager{}
- }
- func (m *Manager) Join(c Tracker) {
- m.connections.Store(c.Metadata().ID, c)
- }
- func (m *Manager) Leave(c Tracker) {
- metadata := c.Metadata()
- _, loaded := m.connections.LoadAndDelete(metadata.ID)
- if loaded {
- metadata.ClosedAt = time.Now()
- m.closedConnectionsAccess.Lock()
- defer m.closedConnectionsAccess.Unlock()
- if m.closedConnections.Len() >= 1000 {
- m.closedConnections.PopFront()
- }
- m.closedConnections.PushBack(metadata)
- }
- }
- func (m *Manager) PushUploaded(size int64) {
- m.uploadTotal.Add(size)
- }
- func (m *Manager) PushDownloaded(size int64) {
- m.downloadTotal.Add(size)
- }
- func (m *Manager) Total() (up int64, down int64) {
- return m.uploadTotal.Load(), m.downloadTotal.Load()
- }
- func (m *Manager) ConnectionsLen() int {
- return m.connections.Len()
- }
- func (m *Manager) Connections() []TrackerMetadata {
- var connections []TrackerMetadata
- m.connections.Range(func(_ uuid.UUID, value Tracker) bool {
- connections = append(connections, value.Metadata())
- return true
- })
- return connections
- }
- func (m *Manager) ClosedConnections() []TrackerMetadata {
- m.closedConnectionsAccess.Lock()
- defer m.closedConnectionsAccess.Unlock()
- return m.closedConnections.Array()
- }
- func (m *Manager) Connection(id uuid.UUID) Tracker {
- connection, loaded := m.connections.Load(id)
- if !loaded {
- return nil
- }
- return connection
- }
- func (m *Manager) Snapshot() *Snapshot {
- var connections []Tracker
- m.connections.Range(func(_ uuid.UUID, value Tracker) bool {
- if value.Metadata().OutboundType != C.TypeDNS {
- connections = append(connections, value)
- }
- return true
- })
- var memStats runtime.MemStats
- runtime.ReadMemStats(&memStats)
- m.memory = memStats.StackInuse + memStats.HeapInuse + memStats.HeapIdle - memStats.HeapReleased
- return &Snapshot{
- Upload: m.uploadTotal.Load(),
- Download: m.downloadTotal.Load(),
- Connections: connections,
- Memory: m.memory,
- }
- }
- func (m *Manager) ResetStatistic() {
- m.uploadTotal.Store(0)
- m.downloadTotal.Store(0)
- }
- type Snapshot struct {
- Download int64
- Upload int64
- Connections []Tracker
- Memory uint64
- }
- func (s *Snapshot) MarshalJSON() ([]byte, error) {
- return json.Marshal(map[string]any{
- "downloadTotal": s.Download,
- "uploadTotal": s.Upload,
- "connections": common.Map(s.Connections, func(t Tracker) TrackerMetadata { return t.Metadata() }),
- "memory": s.Memory,
- })
- }
|