/
dnslookupudp.go
83 lines (65 loc) · 1.98 KB
/
dnslookupudp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package dslvm
import (
"context"
"time"
"github.com/ooni/probe-engine/pkg/logx"
)
// DNSLookupUDPStage is a [Stage] that resolves domain names using an UDP resolver.
type DNSLookupUDPStage struct {
// Domain is the MANDATORY domain to resolve using this DNS resolver.
Domain string
// Output is the MANDATORY channel emitting IP addresses. We will close this
// channel when we have finished streaming the resolved addresses.
Output chan<- string
// Resolver is the MANDATORY resolver endpoint (e.g., [::1]:53).
Resolver string
// Tags contains OPTIONAL tags for the DNS observations.
Tags []string
}
var _ Stage = &DNSLookupUDPStage{}
// Run resolves a Domain using the given Do53 Endpoint and streams the
// results on Output, which is closed when we're done.
//
// This function honours the semaphore returned by the [Runtime] ActiveDNSLookups
// method and waits until it's given the permission to start a lookup.
func (sx *DNSLookupUDPStage) Run(ctx context.Context, rtx Runtime) {
// wait for permission to lookup and signal when done
rtx.ActiveDNSLookups().Wait()
defer rtx.ActiveDNSLookups().Signal()
// make sure we close output when done
defer close(sx.Output)
// create trace
trace := rtx.NewTrace(rtx.IDGenerator().Add(1), rtx.ZeroTime(), sx.Tags...)
// start operation logger
ol := logx.NewOperationLogger(
rtx.Logger(),
"[#%d] DNSLookup[%s/udp] %s",
trace.Index(),
sx.Resolver,
sx.Domain,
)
// setup
const timeout = 4 * time.Second
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
// create the resolver
resolver := trace.NewParallelUDPResolver(
rtx.Logger(),
trace.NewDialerWithoutResolver(rtx.Logger()),
sx.Resolver,
)
// lookup
addrs, err := resolver.LookupHost(ctx, sx.Domain)
// stop the operation logger
ol.Stop(err)
// save the observations
rtx.SaveObservations(maybeTraceToObservations(trace)...)
// handle error case
if err != nil {
return
}
// handle success
for _, addr := range addrs {
sx.Output <- addr
}
}