package sync import ( "fmt" "net" "sort" "sync" "time" "vpnem/internal/models" ) // LatencyResult holds a server's latency measurement. type LatencyResult struct { Tag string `json:"tag"` Region string `json:"region"` Latency int `json:"latency_ms"` // -1 means unreachable } // MeasureLatency pings all servers concurrently and returns results sorted by latency. func MeasureLatency(servers []models.Server, timeout time.Duration) []LatencyResult { var wg sync.WaitGroup results := make([]LatencyResult, len(servers)) for i, s := range servers { wg.Add(1) go func(idx int, srv models.Server) { defer wg.Done() ms := tcpPing(srv.Server, srv.ServerPort, timeout) results[idx] = LatencyResult{ Tag: srv.Tag, Region: srv.Region, Latency: ms, } }(i, s) } wg.Wait() sort.Slice(results, func(i, j int) bool { if results[i].Latency == -1 { return false } if results[j].Latency == -1 { return true } return results[i].Latency < results[j].Latency }) return results } func tcpPing(host string, port int, timeout time.Duration) int { addr := fmt.Sprintf("%s:%d", host, port) start := time.Now() conn, err := net.DialTimeout("tcp", addr, timeout) if err != nil { return -1 } conn.Close() return int(time.Since(start).Milliseconds()) }