整合配置列表
This commit is contained in:
+74
-6
@@ -19,15 +19,57 @@ const (
|
||||
|
||||
// Stats holds live session statistics. Counters are atomic for
|
||||
// lock-free reads from the UI/IPC layer.
|
||||
//
|
||||
// Counters are split by IP address family (v4/v6) at the recording
|
||||
// site via AddRx/AddTx, which inspect the IP version nibble. The
|
||||
// combined RxBytes/TxBytes are derived as the sum of the per-family
|
||||
// counters in Snapshot, so callers that only need the total still
|
||||
// work.
|
||||
type Stats struct {
|
||||
RxBytes atomic.Int64
|
||||
TxBytes atomic.Int64
|
||||
RxBytesV4 atomic.Int64
|
||||
RxBytesV6 atomic.Int64
|
||||
TxBytesV4 atomic.Int64
|
||||
TxBytesV6 atomic.Int64
|
||||
ConnectedAt atomic.Int64 // unix timestamp, 0 = not connected
|
||||
state atomic.Value // State
|
||||
assignedIP atomic.Value // string (IPv4)
|
||||
assignedIP6 atomic.Value // string (IPv6, may be empty)
|
||||
}
|
||||
|
||||
// AddRx records a downloaded packet (WebSocket → TUN) of length n,
|
||||
// routing the bytes to the v4 or v6 counter based on the IP version
|
||||
// nibble of the packet. Packets too short to contain a version byte
|
||||
// or with an unknown version are ignored.
|
||||
func (s *Stats) AddRx(p []byte) {
|
||||
if len(p) == 0 {
|
||||
return
|
||||
}
|
||||
n := int64(len(p))
|
||||
switch p[0] >> 4 {
|
||||
case 4:
|
||||
s.RxBytesV4.Add(n)
|
||||
case 6:
|
||||
s.RxBytesV6.Add(n)
|
||||
}
|
||||
}
|
||||
|
||||
// AddTx records an uploaded packet (TUN → WebSocket) of length n,
|
||||
// routing the bytes to the v4 or v6 counter based on the IP version
|
||||
// nibble of the packet. Packets too short to contain a version byte
|
||||
// or with an unknown version are ignored.
|
||||
func (s *Stats) AddTx(p []byte) {
|
||||
if len(p) == 0 {
|
||||
return
|
||||
}
|
||||
n := int64(len(p))
|
||||
switch p[0] >> 4 {
|
||||
case 4:
|
||||
s.TxBytesV4.Add(n)
|
||||
case 6:
|
||||
s.TxBytesV6.Add(n)
|
||||
}
|
||||
}
|
||||
|
||||
// New creates a Stats instance initialised to the disconnected state.
|
||||
func New() *Stats {
|
||||
s := &Stats{}
|
||||
@@ -67,9 +109,27 @@ func (s *Stats) AssignedIP() string { return s.assignedIP.Load().(string) }
|
||||
func (s *Stats) AssignedIP6() string { return s.assignedIP6.Load().(string) }
|
||||
|
||||
// Snapshot returns a point-in-time copy of all counters.
|
||||
//
|
||||
// Per-family byte counters are read directly. The combined RxBytes/
|
||||
// TxBytes are derived as v4+v6. Speed fields (RxSpeedV4 etc.) are
|
||||
// left zero here; the SessionManager fills them in by computing
|
||||
// per-tick deltas with EWMA smoothing.
|
||||
type Snapshot struct {
|
||||
RxBytes int64
|
||||
TxBytes int64
|
||||
RxBytesV4 int64
|
||||
RxBytesV6 int64
|
||||
TxBytesV4 int64
|
||||
TxBytesV6 int64
|
||||
RxBytes int64 // combined (v4+v6)
|
||||
TxBytes int64 // combined (v4+v6)
|
||||
|
||||
// Speeds in bytes/sec (EWMA-smoothed). The UI converts to bits/sec.
|
||||
RxSpeedV4 int64
|
||||
TxSpeedV4 int64
|
||||
RxSpeedV6 int64
|
||||
TxSpeedV6 int64
|
||||
RxSpeed int64 // combined
|
||||
TxSpeed int64 // combined
|
||||
|
||||
ConnectedAt time.Time
|
||||
AssignedIP string
|
||||
AssignedIP6 string
|
||||
@@ -79,9 +139,17 @@ type Snapshot struct {
|
||||
|
||||
// Snapshot returns a point-in-time copy of the statistics.
|
||||
func (s *Stats) Snapshot() Snapshot {
|
||||
rxv4 := s.RxBytesV4.Load()
|
||||
rxv6 := s.RxBytesV6.Load()
|
||||
txv4 := s.TxBytesV4.Load()
|
||||
txv6 := s.TxBytesV6.Load()
|
||||
snap := Snapshot{
|
||||
RxBytes: s.RxBytes.Load(),
|
||||
TxBytes: s.TxBytes.Load(),
|
||||
RxBytesV4: rxv4,
|
||||
RxBytesV6: rxv6,
|
||||
TxBytesV4: txv4,
|
||||
TxBytesV6: txv6,
|
||||
RxBytes: rxv4 + rxv6,
|
||||
TxBytes: txv4 + txv6,
|
||||
AssignedIP: s.AssignedIP(),
|
||||
AssignedIP6: s.AssignedIP6(),
|
||||
State: s.State(),
|
||||
|
||||
Reference in New Issue
Block a user