Skip to content

Instantly share code, notes, and snippets.

@stzsch
Created May 2, 2023 18:18
Show Gist options
  • Save stzsch/2b1de33d55cf2de89498ea648ccaf182 to your computer and use it in GitHub Desktop.
Save stzsch/2b1de33d55cf2de89498ea648ccaf182 to your computer and use it in GitHub Desktop.
mullvad ping windows
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os/exec"
"sort"
"strconv"
"strings"
"sync"
)
const URL = "https://api.mullvad.net/www/relays/all/"
const NumFastestServers = 10
type Server struct {
Hostname string `json:"hostname"`
CountryCode string `json:"country_code"`
CountryName string `json:"country_name"`
CityCode string `json:"city_code"`
CityName string `json:"city_name"`
Active bool `json:"active"`
Type string `json:"type"`
IPv4AddrIn string `json:"ipv4_addr_in"`
IPv6AddrIn string `json:"ipv6_addr_in"`
NetworkPort int `json:"network_port_speed"`
Latency float64 // New field to store the calculated latency
}
var servers []*Server
func main() {
response, err := http.Get(URL)
if err != nil {
fmt.Println("Request Error", err.Error())
return
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
jsonErr := json.Unmarshal(body, &servers)
if jsonErr != nil {
fmt.Println(jsonErr)
return
}
var wg sync.WaitGroup
fmt.Printf("There are %d active servers\n", len(servers))
for _, server := range servers {
wg.Add(1)
go pingServer(server, &wg)
}
wg.Wait()
// Filter servers with latency over 0ms
fastServers := make([]*Server, 0)
for _, server := range servers {
if server.Latency > 0 {
fastServers = append(fastServers, server)
}
}
// Sort servers by latency in ascending order
sort.Slice(fastServers, func(i, j int) bool {
return fastServers[i].Latency < fastServers[j].Latency
})
// Print the 10 fastest servers
fmt.Println("The 10 fastest servers:")
for i, server := range fastServers {
if i >= 10 {
break
}
fmt.Printf("%d. %s - Latency: %.2f ms\n", i+1, server.Hostname, server.Latency)
}
}
func pingServer(server *Server, wg *sync.WaitGroup) {
defer wg.Done()
cmd := exec.Command("ping", "-n", "4", server.IPv4AddrIn)
output, err := cmd.CombinedOutput()
if err != nil {
fmt.Printf("Failed to ping server %s: %s\n", server.Hostname, err)
return
}
lines := strings.Split(string(output), "\r\n")
var latency float64
for _, line := range lines {
if strings.Contains(line, "Minimum =") && strings.Contains(line, "Maximum =") && strings.Contains(line, "Average =") {
fields := strings.Fields(line)
if len(fields) >= 9 {
latencyStr := strings.TrimSuffix(fields[8], "ms")
latency, err = strconv.ParseFloat(latencyStr, 64)
if err != nil {
fmt.Printf("Failed to parse latency for server %s: %s\n", server.Hostname, err)
return
}
}
break
}
}
server.Latency = latency
fmt.Printf("Server %s - Latency: %.2f ms\n", server.Hostname, server.Latency)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment