package devtunnel import ( "runtime" "sync" "time" "github.com/go-ping/ping" "golang.org/x/exp/slices" "golang.org/x/sync/errgroup" "github.com/coder/coder/cryptorand" ) type Region struct { ID int LocationName string Nodes []Node } type Node struct { ID int `json:"id"` RegionID int `json:"region_id"` HostnameHTTPS string `json:"hostname_https"` HostnameWireguard string `json:"hostname_wireguard"` WireguardPort uint16 `json:"wireguard_port"` AvgLatency time.Duration `json:"avg_latency"` } var Regions = []Region{ { ID: 0, LocationName: "US East Pittsburgh", Nodes: []Node{ { ID: 1, RegionID: 0, HostnameHTTPS: "pit-1.try.coder.app", HostnameWireguard: "pit-1.try.coder.app", WireguardPort: 55551, }, }, }, } func FindClosestNode() (Node, error) { nodes := []Node{} for _, region := range Regions { // Pick a random node from each region. i, err := cryptorand.Intn(len(region.Nodes)) if err != nil { return Node{}, err } nodes = append(nodes, region.Nodes[i]) } var ( nodesMu sync.Mutex eg = errgroup.Group{} ) for i, node := range nodes { i, node := i, node eg.Go(func() error { pinger, err := ping.NewPinger(node.HostnameHTTPS) if err != nil { return err } if runtime.GOOS == "windows" { pinger.SetPrivileged(true) } pinger.Count = 5 err = pinger.Run() if err != nil { return err } nodesMu.Lock() nodes[i].AvgLatency = pinger.Statistics().AvgRtt nodesMu.Unlock() return nil }) } err := eg.Wait() if err != nil { return Node{}, err } slices.SortFunc(nodes, func(i, j Node) bool { return i.AvgLatency < j.AvgLatency }) return nodes[0], nil }