Files
kettuRay/core/ping.go
2026-03-31 14:40:03 +03:00

79 lines
1.7 KiB
Go

package core
import (
"net"
"sync"
"time"
)
// PingResult contains the result of a ping to a server.
type PingResult struct {
Ms int64 // round-trip time in ms, -1 if failed
Color string
}
// PingAddress pings a single address using TCP connect (ICMP requires elevated privileges).
// Returns round-trip time in ms or -1 on failure.
func PingAddress(address string, timeout time.Duration) int64 {
if timeout == 0 {
timeout = 3 * time.Second
}
start := time.Now()
conn, err := net.DialTimeout("tcp", address+":443", timeout)
if err != nil {
return -1
}
conn.Close()
return time.Since(start).Milliseconds()
}
// PingConfig pings a VPN config and returns the result.
func PingConfig(config *VpnConfig) PingResult {
link := TryParseLink(config.Link)
if link == nil {
return PingResult{Ms: -1, Color: "#666"}
}
ms := PingAddress(link.Address, 3*time.Second)
if ms < 0 {
return PingResult{Ms: -1, Color: "#666"}
}
return PingResult{Ms: ms, Color: GetPingColor(ms)}
}
// PingAllConfigs pings all configs concurrently.
func PingAllConfigs(configs []VpnConfig) []PingResult {
results := make([]PingResult, len(configs))
var wg sync.WaitGroup
for i := range configs {
wg.Add(1)
go func(idx int) {
defer wg.Done()
results[idx] = PingConfig(&configs[idx])
}(i)
}
wg.Wait()
return results
}
// GetPingColor returns a color hex code based on ping latency.
func GetPingColor(ms int64) string {
switch {
case ms < 50:
return "#4CAF50" // green
case ms < 100:
return "#8BC34A" // light green
case ms < 150:
return "#CDDC39" // lime
case ms < 200:
return "#FFC107" // amber
case ms < 300:
return "#FF9800" // orange
default:
return "#E53935" // red
}
}