forked from librespeed/speedtest-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhelpers.go
155 lines (127 loc) · 3.33 KB
/
helpers.go
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package web
import (
"crypto/rand"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strconv"
"strings"
log "github.com/sirupsen/logrus"
"github.com/umahmood/haversine"
"github.com/librespeed/speedtest/config"
"github.com/librespeed/speedtest/results"
)
var (
serverCoord haversine.Coord
)
func getRandomData(length int) []byte {
data := make([]byte, length)
if _, err := rand.Read(data); err != nil {
log.Fatalf("Failed to generate random data: %s", err)
}
return data
}
func getIPInfoURL(address string) string {
apiKey := config.LoadedConfig().IPInfoAPIKey
ipInfoURL := `https://ipinfo.io/%s/json`
if address != "" {
ipInfoURL = fmt.Sprintf(ipInfoURL, address)
} else {
ipInfoURL = "https://ipinfo.io/json"
}
if apiKey != "" {
ipInfoURL += "?token=" + apiKey
}
return ipInfoURL
}
func getIPInfo(addr string) results.IPInfoResponse {
var ret results.IPInfoResponse
resp, err := http.DefaultClient.Get(getIPInfoURL(addr))
if err != nil {
log.Errorf("Error getting response from ipinfo.io: %s", err)
return ret
}
raw, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Errorf("Error reading response from ipinfo.io: %s", err)
return ret
}
defer resp.Body.Close()
if err := json.Unmarshal(raw, &ret); err != nil {
log.Errorf("Error parsing response from ipinfo.io: %s", err)
}
return ret
}
func SetServerLocation(conf *config.Config) {
if conf.ServerLat != 0 || conf.ServerLng != 0 {
log.Infof("Configured server coordinates: %.6f, %.6f", conf.ServerLat, conf.ServerLng)
serverCoord.Lat = conf.ServerLat
serverCoord.Lon = conf.ServerLng
return
}
var ret results.IPInfoResponse
resp, err := http.DefaultClient.Get(getIPInfoURL(""))
if err != nil {
log.Errorf("Error getting repsonse from ipinfo.io: %s", err)
return
}
raw, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Errorf("Error reading response from ipinfo.io: %s", err)
return
}
defer resp.Body.Close()
if err := json.Unmarshal(raw, &ret); err != nil {
log.Errorf("Error parsing response from ipinfo.io: %s", err)
return
}
if ret.Location != "" {
serverCoord, err = parseLocationString(ret.Location)
if err != nil {
log.Errorf("Cannot get server coordinates: %s", err)
return
}
}
log.Infof("Fetched server coordinates: %.6f, %.6f", serverCoord.Lat, serverCoord.Lon)
}
func parseLocationString(location string) (haversine.Coord, error) {
var coord haversine.Coord
parts := strings.Split(location, ",")
if len(parts) != 2 {
err := fmt.Errorf("unknown location format: %s", location)
log.Error(err)
return coord, err
}
lat, err := strconv.ParseFloat(parts[0], 64)
if err != nil {
log.Errorf("Error parsing latitude: %s", parts[0])
return coord, err
}
lng, err := strconv.ParseFloat(parts[1], 64)
if err != nil {
log.Errorf("Error parsing longitude: %s", parts[0])
return coord, err
}
coord.Lat = lat
coord.Lon = lng
return coord, nil
}
func calculateDistance(clientLocation string, unit string) string {
clientCoord, err := parseLocationString(clientLocation)
if err != nil {
log.Errorf("Error parsing client coordinates: %s", err)
return ""
}
dist, km := haversine.Distance(clientCoord, serverCoord)
unitString := " mi"
switch unit {
case "km":
dist = km
unitString = " km"
case "NM":
dist = km * 0.539957
unitString = " NM"
}
return fmt.Sprintf("%.2f%s", dist, unitString)
}