Perform an initial benchmark to use servers with the lowest latency

(initially according to the certificate rtt)
This commit is contained in:
Frank Denis 2018-01-17 22:12:34 +01:00
parent 9dcd37093d
commit 8429df82fd
2 changed files with 25 additions and 8 deletions

View File

@ -21,9 +21,9 @@ type CertInfo struct {
CryptoConstruction CryptoConstruction
}
func FetchCurrentCert(proxy *Proxy, proto string, pk ed25519.PublicKey, serverAddress string, providerName string) (CertInfo, error) {
func FetchCurrentCert(proxy *Proxy, proto string, pk ed25519.PublicKey, serverAddress string, providerName string) (CertInfo, int, error) {
if len(pk) != ed25519.PublicKeySize {
return CertInfo{}, errors.New("Invalid public key length")
return CertInfo{}, 0, errors.New("Invalid public key length")
}
if !strings.HasSuffix(providerName, ".") {
providerName = providerName + "."
@ -31,9 +31,9 @@ func FetchCurrentCert(proxy *Proxy, proto string, pk ed25519.PublicKey, serverAd
query := new(dns.Msg)
query.SetQuestion(providerName, dns.TypeTXT)
client := dns.Client{Net: proto, UDPSize: uint16(MaxDNSUDPPacketSize)}
in, _, err := client.Exchange(query, serverAddress)
in, rtt, err := client.Exchange(query, serverAddress)
if err != nil {
return CertInfo{}, err
return CertInfo{}, 0, err
}
now := uint32(time.Now().Unix())
certInfo := CertInfo{CryptoConstruction: UndefinedConstruction}
@ -108,12 +108,12 @@ func FetchCurrentCert(proxy *Proxy, proto string, pk ed25519.PublicKey, serverAd
certInfo.CryptoConstruction = cryptoConstruction
copy(certInfo.ServerPk[:], serverPk[:])
copy(certInfo.MagicQuery[:], binCert[104:112])
dlog.Noticef("[%v] Valid cert (crypto version %d) found", providerName, cryptoConstruction)
dlog.Noticef("[%v] Valid cert (crypto version %d) found - rtt: %dms", providerName, cryptoConstruction, rtt.Nanoseconds()/1000000)
}
if certInfo.CryptoConstruction == UndefinedConstruction {
return certInfo, errors.New("No useable certificate found")
return certInfo, 0, errors.New("No useable certificate found")
}
return certInfo, nil
return certInfo, int(rtt.Nanoseconds() / 1000000), nil
}
func isDigit(b byte) bool { return b >= '0' && b <= '9' }

View File

@ -53,6 +53,7 @@ type ServerInfo struct {
TCPAddr *net.TCPAddr
lastActionTS time.Time
rtt ewma.MovingAverage
initialRtt int
}
type ServersInfo struct {
@ -106,6 +107,21 @@ func (serversInfo *ServersInfo) refresh(proxy *Proxy) (int, error) {
liveServers++
}
}
serversInfo.Lock()
inner := serversInfo.inner
innerLen := len(inner)
for i := 0; i < innerLen; i++ {
for j := i + 1; j < innerLen; j++ {
if inner[j].initialRtt < inner[i].initialRtt {
inner[j], inner[i] = inner[i], inner[j]
}
}
}
serversInfo.inner = inner
if innerLen > 1 {
dlog.Noticef("Server with the lowest initial latency: %s (rtt: %dms)", inner[0].Name, inner[0].initialRtt)
}
serversInfo.Unlock()
return liveServers, err
}
@ -140,7 +156,7 @@ func (serversInfo *ServersInfo) fetchServerInfo(proxy *Proxy, name string, stamp
if err != nil || len(serverPk) != ed25519.PublicKeySize {
dlog.Fatalf("Unsupported public key: [%v]", serverPk)
}
certInfo, err := FetchCurrentCert(proxy, proxy.mainProto, serverPk, stamp.serverAddrStr, stamp.providerName)
certInfo, rtt, err := FetchCurrentCert(proxy, proxy.mainProto, serverPk, stamp.serverAddrStr, stamp.providerName)
if err != nil {
return ServerInfo{}, err
}
@ -161,6 +177,7 @@ func (serversInfo *ServersInfo) fetchServerInfo(proxy *Proxy, name string, stamp
Timeout: proxy.timeout,
UDPAddr: remoteUDPAddr,
TCPAddr: remoteTCPAddr,
initialRtt: rtt,
}
return serverInfo, nil
}