From 9542109d66370e25c0af90042423c950e6f2ba4f Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Thu, 26 Mar 2020 12:53:22 +0100 Subject: [PATCH] Cancel dnsExchange goroutines as soon as we have a best response --- dnscrypt-proxy/dnscrypt_certs.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/dnscrypt-proxy/dnscrypt_certs.go b/dnscrypt-proxy/dnscrypt_certs.go index 505dd6db..ed9aecc4 100644 --- a/dnscrypt-proxy/dnscrypt_certs.go +++ b/dnscrypt-proxy/dnscrypt_certs.go @@ -193,31 +193,42 @@ type dnsExchangeResponse struct { func dnsExchange(proxy *Proxy, proto string, query *dns.Msg, serverAddress string, relayUDPAddr *net.UDPAddr, relayTCPAddr *net.TCPAddr, serverName *string, tryFragmentsSupport bool) (*dns.Msg, time.Duration, bool, error) { for { + cancelChannel := make(chan struct{}) channel := make(chan dnsExchangeResponse) var err error options := 0 - for tries := 2; tries >= 0; tries-- { + for tries := 0; tries < 3; tries++ { if tryFragmentsSupport { queryCopy := query.Copy() queryCopy.Id += uint16(options) go func(query *dns.Msg, delay time.Duration) { - time.Sleep(delay) option := _dnsExchange(proxy, proto, query, serverAddress, relayUDPAddr, relayTCPAddr, 1500) option.fragmentsBlocked = false option.priority = 0 channel <- option + time.Sleep(delay) + select { + case <-cancelChannel: + return + default: + } }(queryCopy, time.Duration(200*tries)*time.Millisecond) options++ } queryCopy := query.Copy() queryCopy.Id += uint16(options) go func(query *dns.Msg, delay time.Duration) { - time.Sleep(delay) option := _dnsExchange(proxy, proto, query, serverAddress, relayUDPAddr, relayTCPAddr, 480) option.fragmentsBlocked = true option.priority = 1 channel <- option + time.Sleep(delay) + select { + case <-cancelChannel: + return + default: + } }(queryCopy, time.Duration(250*tries)*time.Millisecond) options++ } @@ -228,6 +239,7 @@ func dnsExchange(proxy *Proxy, proto string, query *dns.Msg, serverAddress strin (dnsExchangeResponse.priority == bestOption.priority && dnsExchangeResponse.rtt < bestOption.rtt) { bestOption = &dnsExchangeResponse if bestOption.priority == 0 { + close(cancelChannel) break } }