mirror of
https://github.com/luckfox-eng29/kvm.git
synced 2026-01-18 03:28:19 +01:00
network enhanecment / refactor (#361)
* chore(network): improve connectivity check * refactor(network): rewrite network and timesync component * feat(display): show cloud connection status * chore: change logging verbosity * chore(websecure): update log message * fix(ota): validate root certificate when downloading update * feat(ui): add network settings tab * fix(display): cloud connecting animation * fix: golintci issues * feat: add network settings tab * feat(timesync): query servers in parallel * refactor(network): move to internal/network package * feat(timesync): add metrics * refactor(log): move log to internal/logging package * refactor(mdms): move mdns to internal/mdns package * feat(developer): add pprof endpoint * feat(logging): add a simple logging streaming endpoint * fix(mdns): do not start mdns until network is up * feat(network): allow users to update network settings from ui * fix(network): handle errors when net.IPAddr is nil * fix(mdns): scopedLogger SIGSEGV * fix(dhcp): watch directory instead of file to catch fsnotify.Create event * refactor(nbd): move platform-specific code to different files * refactor(native): move platform-specific code to different files * chore: fix linter issues * chore(dev_deploy): allow to override PION_LOG_TRACE
This commit is contained in:
132
internal/timesync/http.go
Normal file
132
internal/timesync/http.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package timesync
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var defaultHTTPUrls = []string{
|
||||
"http://www.gstatic.com/generate_204",
|
||||
"http://cp.cloudflare.com/",
|
||||
"http://edge-http.microsoft.com/captiveportal/generate_204",
|
||||
// Firefox, Apple, and Microsoft have inconsistent results, so we don't use it
|
||||
// "http://detectportal.firefox.com/",
|
||||
// "http://www.apple.com/library/test/success.html",
|
||||
// "http://www.msftconnecttest.com/connecttest.txt",
|
||||
}
|
||||
|
||||
func (t *TimeSync) queryAllHttpTime() (now *time.Time) {
|
||||
chunkSize := 4
|
||||
httpUrls := t.httpUrls
|
||||
|
||||
// shuffle the http urls to avoid always querying the same servers
|
||||
rand.Shuffle(len(httpUrls), func(i, j int) { httpUrls[i], httpUrls[j] = httpUrls[j], httpUrls[i] })
|
||||
|
||||
for i := 0; i < len(httpUrls); i += chunkSize {
|
||||
chunk := httpUrls[i:min(i+chunkSize, len(httpUrls))]
|
||||
results := t.queryMultipleHttp(chunk, timeSyncTimeout)
|
||||
if results != nil {
|
||||
return results
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TimeSync) queryMultipleHttp(urls []string, timeout time.Duration) (now *time.Time) {
|
||||
results := make(chan *time.Time, len(urls))
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
|
||||
for _, url := range urls {
|
||||
go func(url string) {
|
||||
scopedLogger := t.l.With().
|
||||
Str("http_url", url).
|
||||
Logger()
|
||||
|
||||
metricHttpRequestCount.WithLabelValues(url).Inc()
|
||||
metricHttpTotalRequestCount.Inc()
|
||||
|
||||
startTime := time.Now()
|
||||
now, response, err := queryHttpTime(
|
||||
ctx,
|
||||
url,
|
||||
timeout,
|
||||
)
|
||||
duration := time.Since(startTime)
|
||||
|
||||
metricHttpServerLastRTT.WithLabelValues(url).Set(float64(duration.Milliseconds()))
|
||||
metricHttpServerRttHistogram.WithLabelValues(url).Observe(float64(duration.Milliseconds()))
|
||||
|
||||
status := 0
|
||||
if response != nil {
|
||||
status = response.StatusCode
|
||||
}
|
||||
metricHttpServerInfo.WithLabelValues(
|
||||
url,
|
||||
strconv.Itoa(status),
|
||||
).Set(1)
|
||||
|
||||
if err == nil {
|
||||
metricHttpTotalSuccessCount.Inc()
|
||||
metricHttpSuccessCount.WithLabelValues(url).Inc()
|
||||
|
||||
requestId := response.Header.Get("X-Request-Id")
|
||||
if requestId != "" {
|
||||
requestId = response.Header.Get("X-Msedge-Ref")
|
||||
}
|
||||
if requestId == "" {
|
||||
requestId = response.Header.Get("Cf-Ray")
|
||||
}
|
||||
scopedLogger.Info().
|
||||
Str("time", now.Format(time.RFC3339)).
|
||||
Int("status", status).
|
||||
Str("request_id", requestId).
|
||||
Str("time_taken", duration.String()).
|
||||
Msg("HTTP server returned time")
|
||||
|
||||
cancel()
|
||||
results <- now
|
||||
} else if errors.Is(err, context.Canceled) {
|
||||
metricHttpCancelCount.WithLabelValues(url).Inc()
|
||||
metricHttpTotalCancelCount.Inc()
|
||||
} else {
|
||||
scopedLogger.Warn().
|
||||
Str("error", err.Error()).
|
||||
Int("status", status).
|
||||
Msg("failed to query HTTP server")
|
||||
}
|
||||
}(url)
|
||||
}
|
||||
|
||||
return <-results
|
||||
}
|
||||
|
||||
func queryHttpTime(
|
||||
ctx context.Context,
|
||||
url string,
|
||||
timeout time.Duration,
|
||||
) (now *time.Time, response *http.Response, err error) {
|
||||
client := http.Client{
|
||||
Timeout: timeout,
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
dateStr := resp.Header.Get("Date")
|
||||
parsedTime, err := time.Parse(time.RFC1123, dateStr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return &parsedTime, resp, nil
|
||||
}
|
||||
Reference in New Issue
Block a user