86 lines
2.2 KiB
Go
86 lines
2.2 KiB
Go
// Package stats provides atomic counters for VPN session statistics.
|
|
package stats
|
|
|
|
import (
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
// State represents the current VPN session state.
|
|
type State string
|
|
|
|
const (
|
|
StateDisconnected State = "disconnected"
|
|
StateConnecting State = "connecting"
|
|
StateConnected State = "connected"
|
|
StateReconnecting State = "reconnecting"
|
|
StateError State = "error"
|
|
)
|
|
|
|
// Stats holds live session statistics. Counters are atomic for
|
|
// lock-free reads from the UI/IPC layer.
|
|
type Stats struct {
|
|
RxBytes atomic.Int64
|
|
TxBytes atomic.Int64
|
|
ConnectedAt atomic.Int64 // unix timestamp, 0 = not connected
|
|
state atomic.Value // State
|
|
assignedIP atomic.Value // string
|
|
}
|
|
|
|
// New creates a Stats instance initialised to the disconnected state.
|
|
func New() *Stats {
|
|
s := &Stats{}
|
|
s.state.Store(StateDisconnected)
|
|
s.assignedIP.Store("")
|
|
return s
|
|
}
|
|
|
|
// SetState updates the current state atomically.
|
|
func (s *Stats) SetState(st State) { s.state.Store(st) }
|
|
|
|
// State returns the current state.
|
|
func (s *Stats) State() State { return s.state.Load().(State) }
|
|
|
|
// SetConnected marks the session as connected, recording the time and IP.
|
|
func (s *Stats) SetConnected(ip string) {
|
|
s.ConnectedAt.Store(time.Now().Unix())
|
|
s.assignedIP.Store(ip)
|
|
s.state.Store(StateConnected)
|
|
}
|
|
|
|
// SetDisconnected clears the connection metadata.
|
|
func (s *Stats) SetDisconnected() {
|
|
s.ConnectedAt.Store(0)
|
|
s.assignedIP.Store("")
|
|
s.state.Store(StateDisconnected)
|
|
}
|
|
|
|
// AssignedIP returns the server-assigned tunnel IP.
|
|
func (s *Stats) AssignedIP() string { return s.assignedIP.Load().(string) }
|
|
|
|
// Snapshot returns a point-in-time copy of all counters.
|
|
type Snapshot struct {
|
|
RxBytes int64
|
|
TxBytes int64
|
|
ConnectedAt time.Time
|
|
AssignedIP string
|
|
State State
|
|
Uptime time.Duration
|
|
}
|
|
|
|
// Snapshot returns a point-in-time copy of the statistics.
|
|
func (s *Stats) Snapshot() Snapshot {
|
|
snap := Snapshot{
|
|
RxBytes: s.RxBytes.Load(),
|
|
TxBytes: s.TxBytes.Load(),
|
|
AssignedIP: s.AssignedIP(),
|
|
State: s.State(),
|
|
}
|
|
ts := s.ConnectedAt.Load()
|
|
if ts > 0 {
|
|
snap.ConnectedAt = time.Unix(ts, 0)
|
|
snap.Uptime = time.Since(snap.ConnectedAt)
|
|
}
|
|
return snap
|
|
}
|