-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: move webconnectivitylte algos to webconnectivityalgo (#1496)
This diff refactors webconnectivitylte by moving some algorithms inside the new webconnectivityalgo package. In subsequent commits, we'll seize the opportunity of adding tests for these algorithms, refactor the code, and add specific tests. Part of ooni/probe#2669. While there, recognize that the webconnectivityqa package does not belong to internal/experiment but to internal.
- Loading branch information
1 parent
37db467
commit a6f3ca4
Showing
44 changed files
with
190 additions
and
148 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,8 @@ | ||
package webconnectivitylte | ||
|
||
import ( | ||
"context" | ||
"sync" | ||
"time" | ||
|
||
"github.com/ooni/probe-cli/v3/internal/model" | ||
"github.com/ooni/probe-cli/v3/internal/netxlite" | ||
"github.com/ooni/probe-cli/v3/internal/webconnectivityalgo" | ||
) | ||
|
||
// TODO(bassosimone): this code needs refining before we can merge it inside | ||
// master. For one, we already have systemv4 info. Additionally, it would | ||
// be neat to avoid additional AAAA queries. Furthermore, we should also see | ||
// to implement support for IPv6 only clients as well. | ||
|
||
// DNSWhoamiService is a service that performs DNS whoami lookups. | ||
type DNSWhoamiService struct { | ||
// mu provides mutual exclusion | ||
mu *sync.Mutex | ||
|
||
// systemv4 contains systemv4 results | ||
systemv4 []DNSWhoamiInfoEntry | ||
|
||
// udpv4 contains udpv4 results | ||
udpv4 map[string][]DNSWhoamiInfoEntry | ||
} | ||
|
||
// SystemV4 returns the results of querying using the system resolver and IPv4. | ||
func (svc *DNSWhoamiService) SystemV4(ctx context.Context) ([]DNSWhoamiInfoEntry, bool) { | ||
svc.mu.Lock() | ||
defer svc.mu.Unlock() | ||
if len(svc.systemv4) <= 0 { | ||
ctx, cancel := context.WithTimeout(ctx, 4*time.Second) | ||
defer cancel() | ||
netx := &netxlite.Netx{} | ||
reso := netx.NewStdlibResolver(model.DiscardLogger) | ||
addrs, err := reso.LookupHost(ctx, "whoami.v4.powerdns.org") | ||
if err != nil || len(addrs) < 1 { | ||
return nil, false | ||
} | ||
svc.systemv4 = []DNSWhoamiInfoEntry{{ | ||
Address: addrs[0], | ||
}} | ||
} | ||
return svc.systemv4, len(svc.systemv4) > 0 | ||
} | ||
|
||
// UDPv4 returns the results of querying a given UDP resolver and IPv4. | ||
func (svc *DNSWhoamiService) UDPv4(ctx context.Context, address string) ([]DNSWhoamiInfoEntry, bool) { | ||
svc.mu.Lock() | ||
defer svc.mu.Unlock() | ||
if len(svc.udpv4[address]) <= 0 { | ||
ctx, cancel := context.WithTimeout(ctx, 4*time.Second) | ||
defer cancel() | ||
netx := &netxlite.Netx{} | ||
dialer := netxlite.NewDialerWithStdlibResolver(model.DiscardLogger) | ||
reso := netx.NewParallelUDPResolver(model.DiscardLogger, dialer, address) | ||
// TODO(bassosimone): this should actually only send an A query. Sending an AAAA | ||
// query is _way_ unnecessary since we know that only A is going to work. | ||
addrs, err := reso.LookupHost(ctx, "whoami.v4.powerdns.org") | ||
if err != nil || len(addrs) < 1 { | ||
return nil, false | ||
} | ||
svc.udpv4[address] = []DNSWhoamiInfoEntry{{ | ||
Address: addrs[0], | ||
}} | ||
} | ||
value := svc.udpv4[address] | ||
return value, len(value) > 0 | ||
} | ||
|
||
// TODO(bassosimone): consider factoring this code and keeping state | ||
// on disk rather than on memory. | ||
|
||
// DNSWhoamiSingleton is the DNSWhoamiService singleton. | ||
var DNSWhoamiSingleton = &DNSWhoamiService{ | ||
mu: &sync.Mutex{}, | ||
systemv4: []DNSWhoamiInfoEntry{}, | ||
udpv4: map[string][]DNSWhoamiInfoEntry{}, | ||
} | ||
var DNSWhoamiSingleton = webconnectivityalgo.NewDNSWhoamiService() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package webconnectivityalgo | ||
|
||
// | ||
// DNS-over-HTTPS | ||
// | ||
// Code to manage DNS-over-HTTPS testing. | ||
// | ||
|
||
import ( | ||
"math/rand" | ||
"sync" | ||
"time" | ||
) | ||
|
||
// TODO(bassosimone): consider whether factoring out this code | ||
// and storing the state on disk instead of using memory | ||
|
||
// TODO(bassosimone): consider unifying somehow this code and | ||
// the systemresolver code (or maybe just the list of resolvers) | ||
|
||
// OpportunisticDNSOverHTTPSURLProvider allows to perform opportunistic DNS-over-HTTPS | ||
// measurements as part of Web Connectivity LTE. The zero value of this struct is not valid, | ||
// please use [NewOpportunisticDNSOverHTTPSURLProvider] to construct. | ||
type OpportunisticDNSOverHTTPSURLProvider struct { | ||
// interval is the next interval after which to measure. | ||
interval time.Duration | ||
|
||
// mu provides mutual exclusion | ||
mu *sync.Mutex | ||
|
||
// rnd is the random number generator to use. | ||
rnd *rand.Rand | ||
|
||
// t is when we last run an opportunistic measurement. | ||
t time.Time | ||
|
||
// urls contains the urls of known DoH services. | ||
urls []string | ||
} | ||
|
||
// NewOpportunisticDNSOverHTTPSURLProvider creates a new [*OpportunisticDNSOverHTTPSURLProvider]. | ||
func NewOpportunisticDNSOverHTTPSURLProvider(urls ...string) *OpportunisticDNSOverHTTPSURLProvider { | ||
return &OpportunisticDNSOverHTTPSURLProvider{ | ||
interval: 0, | ||
mu: &sync.Mutex{}, | ||
rnd: rand.New(rand.NewSource(time.Now().UnixNano())), | ||
t: time.Time{}, | ||
urls: urls, | ||
} | ||
} | ||
|
||
// MaybeNextURL returns the next URL to measure, if any. Our aim is to perform | ||
// periodic, opportunistic DoH measurements as part of Web Connectivity. | ||
func (o *OpportunisticDNSOverHTTPSURLProvider) MaybeNextURL() (string, bool) { | ||
now := time.Now() | ||
o.mu.Lock() | ||
defer o.mu.Unlock() | ||
if o.t.IsZero() || now.Sub(o.t) > o.interval { | ||
o.rnd.Shuffle(len(o.urls), func(i, j int) { | ||
o.urls[i], o.urls[j] = o.urls[j], o.urls[i] | ||
}) | ||
o.t = now | ||
o.interval = time.Duration(20+o.rnd.Uint32()%20) * time.Second | ||
return o.urls[0], true | ||
} | ||
return "", false | ||
} |
Oops, something went wrong.