1153850aca
While there, `.../internal/sessionresolver` => `.../sessionresolver` See https://github.com/ooni/probe/issues/2255
121 lines
3.1 KiB
Go
121 lines
3.1 KiB
Go
package sessionresolver
|
|
|
|
//
|
|
// Code for creating a new child resolver
|
|
//
|
|
|
|
import (
|
|
"math/rand"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
|
"github.com/ooni/probe-cli/v3/internal/model"
|
|
)
|
|
|
|
// resolvemaker contains rules for making a resolver.
|
|
type resolvermaker struct {
|
|
url string
|
|
score float64
|
|
}
|
|
|
|
// systemResolverURL is the URL of the system resolver.
|
|
const systemResolverURL = "system:///"
|
|
|
|
// allmakers contains all the makers in a list. We use the http3
|
|
// prefix to indicate we wanna use http3. The code will translate
|
|
// this to https and set the proper netx options.
|
|
var allmakers = []*resolvermaker{{
|
|
url: "https://cloudflare-dns.com/dns-query",
|
|
}, {
|
|
url: "http3://cloudflare-dns.com/dns-query",
|
|
}, {
|
|
url: "https://dns.google/dns-query",
|
|
}, {
|
|
url: "http3://dns.google/dns-query",
|
|
}, {
|
|
url: "https://dns.quad9.net/dns-query",
|
|
}, {
|
|
url: systemResolverURL,
|
|
}, {
|
|
url: "https://mozilla.cloudflare-dns.com/dns-query",
|
|
}, {
|
|
url: "http3://mozilla.cloudflare-dns.com/dns-query",
|
|
}}
|
|
|
|
// allbyurl contains all the resolvermakers by URL
|
|
var allbyurl map[string]*resolvermaker
|
|
|
|
// init fills allbyname and gives a nonzero initial score
|
|
// to all resolvers except for the system resolver. We set
|
|
// the system resolver score to zero, so that it's less
|
|
// likely than other resolvers in this list.
|
|
func init() {
|
|
allbyurl = make(map[string]*resolvermaker)
|
|
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
for _, e := range allmakers {
|
|
allbyurl[e.url] = e
|
|
if e.url != systemResolverURL {
|
|
e.score = rng.Float64()
|
|
}
|
|
}
|
|
}
|
|
|
|
// logger returns the configured logger or a default
|
|
func (r *Resolver) logger() model.Logger {
|
|
return model.ValidLoggerOrDefault(r.Logger)
|
|
}
|
|
|
|
// newChildResolver creates a new child model.Resolver.
|
|
func (r *Resolver) newChildResolver(h3 bool, URL string) (model.Resolver, error) {
|
|
if r.newChildResolverFn != nil {
|
|
return r.newChildResolverFn(h3, URL)
|
|
}
|
|
return netx.NewDNSClient(netx.Config{
|
|
BogonIsError: true,
|
|
ByteCounter: r.ByteCounter, // nil is handled by netx
|
|
HTTP3Enabled: h3,
|
|
Logger: r.logger(),
|
|
ProxyURL: r.ProxyURL,
|
|
}, URL)
|
|
}
|
|
|
|
// newresolver creates a new resolver with the given config and URL. This is
|
|
// where we expand http3 to https and set the h3 options.
|
|
func (r *Resolver) newresolver(URL string) (model.Resolver, error) {
|
|
h3 := strings.HasPrefix(URL, "http3://")
|
|
if h3 {
|
|
URL = strings.Replace(URL, "http3://", "https://", 1)
|
|
}
|
|
return r.newChildResolver(h3, URL)
|
|
}
|
|
|
|
// getresolver returns a resolver with the given URL. This function caches
|
|
// already allocated resolvers so we only allocate them once.
|
|
func (r *Resolver) getresolver(URL string) (model.Resolver, error) {
|
|
defer r.mu.Unlock()
|
|
r.mu.Lock()
|
|
if re, found := r.res[URL]; found {
|
|
return re, nil // already created
|
|
}
|
|
re, err := r.newresolver(URL)
|
|
if err != nil {
|
|
return nil, err // config err?
|
|
}
|
|
if r.res == nil {
|
|
r.res = make(map[string]model.Resolver)
|
|
}
|
|
r.res[URL] = re
|
|
return re, nil
|
|
}
|
|
|
|
// closeall closes the cached resolvers.
|
|
func (r *Resolver) closeall() {
|
|
defer r.mu.Unlock()
|
|
r.mu.Lock()
|
|
for _, re := range r.res {
|
|
re.CloseIdleConnections()
|
|
}
|
|
r.res = nil
|
|
}
|