Welcome to mirror list, hosted at ThFree Co, Russian Federation.

sys_windows.go « sys « util - github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: f3eae07661a7bf19714d602e52e174e1cb06117f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//go:build windows
// +build windows

package sys

import (
	"errors"
	"sync"
	"syscall"
	"unsafe"

	"github.com/shirou/gopsutil/v4/net"
)

func GetConnectionCount(proto string) (int, error) {
	if proto != "tcp" && proto != "udp" {
		return 0, errors.New("invalid protocol")
	}

	stats, err := net.Connections(proto)
	if err != nil {
		return 0, err
	}
	return len(stats), nil
}

func GetTCPCount() (int, error) {
	return GetConnectionCount("tcp")
}

func GetUDPCount() (int, error) {
	return GetConnectionCount("udp")
}

// --- CPU Utilization (Windows native) ---

var (
	modKernel32        = syscall.NewLazyDLL("kernel32.dll")
	procGetSystemTimes = modKernel32.NewProc("GetSystemTimes")

	cpuMu      sync.Mutex
	lastIdle   uint64
	lastKernel uint64
	lastUser   uint64
	hasLast    bool
)

type filetime struct {
	LowDateTime  uint32
	HighDateTime uint32
}

func ftToUint64(ft filetime) uint64 {
	return (uint64(ft.HighDateTime) << 32) | uint64(ft.LowDateTime)
}

// CPUPercentRaw returns the instantaneous total CPU utilization percentage using
// Windows GetSystemTimes across all logical processors. The first call returns 0
// as it initializes the baseline. Subsequent calls compute deltas.
func CPUPercentRaw() (float64, error) {
	var idleFT, kernelFT, userFT filetime
	r1, _, e1 := procGetSystemTimes.Call(
		uintptr(unsafe.Pointer(&idleFT)),
		uintptr(unsafe.Pointer(&kernelFT)),
		uintptr(unsafe.Pointer(&userFT)),
	)
	if r1 == 0 { // failure
		if e1 != nil {
			return 0, e1
		}
		return 0, syscall.GetLastError()
	}

	idle := ftToUint64(idleFT)
	kernel := ftToUint64(kernelFT)
	user := ftToUint64(userFT)

	cpuMu.Lock()
	defer cpuMu.Unlock()

	if !hasLast {
		lastIdle = idle
		lastKernel = kernel
		lastUser = user
		hasLast = true
		return 0, nil
	}

	idleDelta := idle - lastIdle
	kernelDelta := kernel - lastKernel
	userDelta := user - lastUser

	// Update for next call
	lastIdle = idle
	lastKernel = kernel
	lastUser = user

	total := kernelDelta + userDelta
	if total == 0 {
		return 0, nil
	}
	// On Windows, kernel time includes idle time; busy = total - idle
	busy := total - idleDelta

	pct := float64(busy) / float64(total) * 100.0
	// lower bound not needed; ratios of uint64 are non-negative
	if pct > 100 {
		pct = 100
	}
	return pct, nil
}