-
Notifications
You must be signed in to change notification settings - Fork 1
/
dot_client.go
93 lines (73 loc) · 1.42 KB
/
dot_client.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
84
85
86
87
88
89
90
91
92
93
package main
import (
"log"
"net"
"sync"
"github.com/miekg/dns"
)
type DOTClient struct {
urls []string
conns map[string]*dns.Conn
client *dns.Client
// Last used index
lIndex int
logQueries bool
sync.Mutex
}
func (c *DOTClient) GetDNSResponse(msg *dns.Msg) (*dns.Msg, error) {
c.Lock()
url := c.urls[c.lIndex]
// Increase last index
c.lIndex++
if c.lIndex == len(c.urls) {
c.lIndex = 0
}
c.Unlock()
log.Printf("log queries: %v", c.logQueries)
if c.logQueries {
log.Printf("Sending to %s for query: %s", url, msg.Question[0].String())
}
var r *dns.Msg
var makeconn bool
for i := 0; i < 5; i++ {
conn, err := c.getConn(url, makeconn)
if err != nil {
return &dns.Msg{}, err
}
r, _, err = c.client.ExchangeWithConn(msg, conn)
if err != nil {
makeconn = true
continue
}
break
}
return r, nil
}
func (c *DOTClient) getConn(url string, makeconn bool) (*dns.Conn, error) {
c.Lock()
defer c.Unlock()
if conn, ok := c.conns[url]; ok {
if makeconn {
goto makeConn
}
return conn, nil
}
makeConn:
conn, err := c.client.Dial(url)
if err != nil {
return nil, err
}
c.conns[url] = conn
return conn, nil
}
func NewDOTClient(urls []string, dialer *net.Dialer, logQueries bool) (*DOTClient, error) {
return &DOTClient{
urls: urls,
client: &dns.Client{
Net: "tcp-tls",
Dialer: dialer,
},
conns: map[string]*dns.Conn{},
logQueries: logQueries,
}, nil
}