124 lines
3.0 KiB
Go
124 lines
3.0 KiB
Go
|
package archival
|
||
|
|
||
|
//
|
||
|
// Saves DNS lookup events
|
||
|
//
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"time"
|
||
|
|
||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||
|
)
|
||
|
|
||
|
// DNSLookupEvent contains the results of a DNS lookup.
|
||
|
type DNSLookupEvent struct {
|
||
|
ALPNs []string
|
||
|
Addresses []string
|
||
|
Domain string
|
||
|
Failure error
|
||
|
Finished time.Time
|
||
|
LookupType string
|
||
|
ResolverAddress string
|
||
|
ResolverNetwork string
|
||
|
Started time.Time
|
||
|
}
|
||
|
|
||
|
// LookupHost performs a host lookup with the given resolver
|
||
|
// and saves the results into the saver.
|
||
|
func (s *Saver) LookupHost(ctx context.Context, reso model.Resolver, domain string) ([]string, error) {
|
||
|
started := time.Now()
|
||
|
addrs, err := reso.LookupHost(ctx, domain)
|
||
|
s.appendLookupHostEvent(&DNSLookupEvent{
|
||
|
ALPNs: nil,
|
||
|
Addresses: addrs,
|
||
|
Domain: domain,
|
||
|
Failure: err,
|
||
|
Finished: time.Now(),
|
||
|
LookupType: "getaddrinfo",
|
||
|
ResolverAddress: reso.Address(),
|
||
|
ResolverNetwork: reso.Network(),
|
||
|
Started: started,
|
||
|
})
|
||
|
return addrs, err
|
||
|
}
|
||
|
|
||
|
func (s *Saver) appendLookupHostEvent(ev *DNSLookupEvent) {
|
||
|
s.mu.Lock()
|
||
|
s.trace.DNSLookupHost = append(s.trace.DNSLookupHost, ev)
|
||
|
s.mu.Unlock()
|
||
|
}
|
||
|
|
||
|
// LookupHTTPS performs an HTTPSSvc-record lookup using the given
|
||
|
// resolver and saves the results into the saver.
|
||
|
func (s *Saver) LookupHTTPS(ctx context.Context, reso model.Resolver, domain string) (*model.HTTPSSvc, error) {
|
||
|
started := time.Now()
|
||
|
https, err := reso.LookupHTTPS(ctx, domain)
|
||
|
s.appendLookupHTTPSEvent(&DNSLookupEvent{
|
||
|
ALPNs: s.safeALPNs(https),
|
||
|
Addresses: s.safeAddresses(https),
|
||
|
Domain: domain,
|
||
|
Failure: err,
|
||
|
Finished: time.Now(),
|
||
|
LookupType: "https",
|
||
|
ResolverAddress: reso.Address(),
|
||
|
ResolverNetwork: reso.Network(),
|
||
|
Started: started,
|
||
|
})
|
||
|
return https, err
|
||
|
}
|
||
|
|
||
|
func (s *Saver) appendLookupHTTPSEvent(ev *DNSLookupEvent) {
|
||
|
s.mu.Lock()
|
||
|
s.trace.DNSLookupHTTPS = append(s.trace.DNSLookupHTTPS, ev)
|
||
|
s.mu.Unlock()
|
||
|
}
|
||
|
|
||
|
func (s *Saver) safeALPNs(https *model.HTTPSSvc) (out []string) {
|
||
|
if https != nil {
|
||
|
out = https.ALPN
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (s *Saver) safeAddresses(https *model.HTTPSSvc) (out []string) {
|
||
|
if https != nil {
|
||
|
out = append(out, https.IPv4...)
|
||
|
out = append(out, https.IPv6...)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// DNSRoundTripEvent contains the result of a DNS round trip.
|
||
|
type DNSRoundTripEvent struct {
|
||
|
Address string
|
||
|
Failure error
|
||
|
Finished time.Time
|
||
|
Network string
|
||
|
Query []byte
|
||
|
Reply []byte
|
||
|
Started time.Time
|
||
|
}
|
||
|
|
||
|
// DNSRoundTrip implements ArchivalSaver.DNSRoundTrip.
|
||
|
func (s *Saver) DNSRoundTrip(ctx context.Context, txp model.DNSTransport, query []byte) ([]byte, error) {
|
||
|
started := time.Now()
|
||
|
reply, err := txp.RoundTrip(ctx, query)
|
||
|
s.appendDNSRoundTripEvent(&DNSRoundTripEvent{
|
||
|
Address: txp.Address(),
|
||
|
Failure: err,
|
||
|
Finished: time.Now(),
|
||
|
Network: txp.Network(),
|
||
|
Query: query,
|
||
|
Reply: reply,
|
||
|
Started: started,
|
||
|
})
|
||
|
return reply, err
|
||
|
}
|
||
|
|
||
|
func (s *Saver) appendDNSRoundTripEvent(ev *DNSRoundTripEvent) {
|
||
|
s.mu.Lock()
|
||
|
s.trace.DNSRoundTrip = append(s.trace.DNSRoundTrip, ev)
|
||
|
s.mu.Unlock()
|
||
|
}
|