Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
G
gost
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
gost
Commits
a7d49f0b
Commit
a7d49f0b
authored
Dec 27, 2018
by
ginuerzh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
DNS resolver support DoH #335
parent
02f1d099
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
431 additions
and
58 deletions
+431
-58
cmd/gost/.config/dns.txt
cmd/gost/.config/dns.txt
+1
-0
cmd/gost/cfg.go
cmd/gost/cfg.go
+21
-4
resolver.go
resolver.go
+188
-54
resolver_test.go
resolver_test.go
+221
-0
No files found.
cmd/gost/.config/dns.txt
View file @
a7d49f0b
...
@@ -10,6 +10,7 @@ reload 10s
...
@@ -10,6 +10,7 @@ reload 10s
# ip[:port] [protocol] [hostname]
# ip[:port] [protocol] [hostname]
1.1.1.1:853 tls cloudflare-dns.com
1.1.1.1:853 tls cloudflare-dns.com
https://1.0.0.1/dns-query https
8.8.8.8
8.8.8.8
8.8.8.8 tcp
8.8.8.8 tcp
1.1.1.1 udp
1.1.1.1 udp
...
...
cmd/gost/cfg.go
View file @
a7d49f0b
...
@@ -207,17 +207,34 @@ func parseResolver(cfg string) gost.Resolver {
...
@@ -207,17 +207,34 @@ func parseResolver(cfg string) gost.Resolver {
if
s
==
""
{
if
s
==
""
{
continue
continue
}
}
if
strings
.
HasPrefix
(
s
,
"https"
)
{
ns
:=
gost
.
NameServer
{
Addr
:
s
,
Protocol
:
"https"
,
}
if
err
:=
ns
.
Init
();
err
==
nil
{
nss
=
append
(
nss
,
ns
)
}
continue
}
ss
:=
strings
.
Split
(
s
,
"/"
)
ss
:=
strings
.
Split
(
s
,
"/"
)
if
len
(
ss
)
==
1
{
if
len
(
ss
)
==
1
{
ns
s
=
append
(
nss
,
gost
.
NameServer
{
ns
:=
gost
.
NameServer
{
Addr
:
ss
[
0
],
Addr
:
ss
[
0
],
})
}
if
err
:=
ns
.
Init
();
err
==
nil
{
nss
=
append
(
nss
,
ns
)
}
}
}
if
len
(
ss
)
==
2
{
if
len
(
ss
)
==
2
{
ns
s
=
append
(
nss
,
gost
.
NameServer
{
ns
:=
gost
.
NameServer
{
Addr
:
ss
[
0
],
Addr
:
ss
[
0
],
Protocol
:
ss
[
1
],
Protocol
:
ss
[
1
],
})
}
if
err
:=
ns
.
Init
();
err
==
nil
{
nss
=
append
(
nss
,
ns
)
}
}
}
}
}
return
gost
.
NewResolver
(
timeout
,
ttl
,
nss
...
)
return
gost
.
NewResolver
(
timeout
,
ttl
,
nss
...
)
...
...
resolver.go
View file @
a7d49f0b
...
@@ -3,23 +3,28 @@ package gost
...
@@ -3,23 +3,28 @@ package gost
import
(
import
(
"bufio"
"bufio"
"bytes"
"bytes"
"context"
"crypto/tls"
"crypto/tls"
"fmt"
"fmt"
"io"
"io"
"io/ioutil"
"net"
"net"
"net/http"
"net/url"
"strings"
"strings"
"sync"
"sync"
"time"
"time"
"github.com/go-log/log"
"github.com/go-log/log"
"github.com/miekg/dns"
"github.com/miekg/dns"
"golang.org/x/net/http2"
)
)
var
(
var
(
// DefaultResolverTimeout is the default timeout for name resolution.
// DefaultResolverTimeout is the default timeout for name resolution.
DefaultResolverTimeout
=
30
*
time
.
Second
DefaultResolverTimeout
=
5
*
time
.
Second
// DefaultResolverTTL is the default cache TTL for name resolution.
// DefaultResolverTTL is the default cache TTL for name resolution.
DefaultResolverTTL
=
60
*
time
.
Second
DefaultResolverTTL
=
1
*
time
.
Hour
)
)
// Resolver is a name resolver for domain name.
// Resolver is a name resolver for domain name.
...
@@ -39,9 +44,73 @@ type ReloadResolver interface {
...
@@ -39,9 +44,73 @@ type ReloadResolver interface {
// NameServer is a name server.
// NameServer is a name server.
// Currently supported protocol: TCP, UDP and TLS.
// Currently supported protocol: TCP, UDP and TLS.
type
NameServer
struct
{
type
NameServer
struct
{
Addr
string
Addr
string
Protocol
string
Protocol
string
Hostname
string
// for TLS handshake verification
Hostname
string
// for TLS handshake verification
Timeout
time
.
Duration
exchanger
Exchanger
}
// Init initializes the name server.
func
(
ns
*
NameServer
)
Init
()
error
{
switch
strings
.
ToLower
(
ns
.
Protocol
)
{
case
"tcp"
:
ns
.
exchanger
=
&
dnsExchanger
{
endpoint
:
ns
.
Addr
,
client
:
&
dns
.
Client
{
Net
:
"tcp"
,
Timeout
:
ns
.
Timeout
,
},
}
case
"tls"
:
cfg
:=
&
tls
.
Config
{
ServerName
:
ns
.
Hostname
,
}
if
cfg
.
ServerName
==
""
{
cfg
.
InsecureSkipVerify
=
true
}
ns
.
exchanger
=
&
dnsExchanger
{
endpoint
:
ns
.
Addr
,
client
:
&
dns
.
Client
{
Net
:
"tcp-tls"
,
Timeout
:
ns
.
Timeout
,
TLSConfig
:
cfg
,
},
}
case
"https"
:
u
,
err
:=
url
.
Parse
(
ns
.
Addr
)
if
err
!=
nil
{
return
err
}
cfg
:=
&
tls
.
Config
{
ServerName
:
u
.
Hostname
()}
transport
:=
&
http
.
Transport
{
TLSClientConfig
:
cfg
,
DisableCompression
:
true
,
MaxIdleConns
:
1
,
}
http2
.
ConfigureTransport
(
transport
)
ns
.
exchanger
=
&
dohExchanger
{
endpoint
:
u
,
client
:
&
http
.
Client
{
Transport
:
transport
,
Timeout
:
ns
.
Timeout
,
},
}
case
"udp"
:
fallthrough
default
:
ns
.
exchanger
=
&
dnsExchanger
{
endpoint
:
ns
.
Addr
,
client
:
&
dns
.
Client
{
Net
:
"udp"
,
Timeout
:
ns
.
Timeout
,
},
}
}
return
nil
}
}
func
(
ns
NameServer
)
String
()
string
{
func
(
ns
NameServer
)
String
()
string
{
...
@@ -62,26 +131,19 @@ type resolverCacheItem struct {
...
@@ -62,26 +131,19 @@ type resolverCacheItem struct {
}
}
type
resolver
struct
{
type
resolver
struct
{
Resolver
*
net
.
Resolver
Servers
[]
NameServer
Servers
[]
NameServer
mCache
*
sync
.
Map
mCache
*
sync
.
Map
Timeout
time
.
Duration
Timeout
time
.
Duration
TTL
time
.
Duration
TTL
time
.
Duration
period
time
.
Duration
period
time
.
Duration
domain
string
domain
string
stopped
chan
struct
{}
stopped
chan
struct
{}
mux
sync
.
RWMutex
mux
sync
.
RWMutex
}
}
// NewResolver create a new Resolver with the given name servers and resolution timeout.
// NewResolver create a new Resolver with the given name servers and resolution timeout.
func
NewResolver
(
timeout
,
ttl
time
.
Duration
,
servers
...
NameServer
)
ReloadResolver
{
func
NewResolver
(
timeout
,
ttl
time
.
Duration
,
servers
...
NameServer
)
ReloadResolver
{
r
:=
&
resolver
{
r
:=
newResolver
(
timeout
,
ttl
,
servers
...
)
Servers
:
servers
,
Timeout
:
timeout
,
TTL
:
ttl
,
mCache
:
&
sync
.
Map
{},
stopped
:
make
(
chan
struct
{}),
}
if
r
.
Timeout
<=
0
{
if
r
.
Timeout
<=
0
{
r
.
Timeout
=
DefaultResolverTimeout
r
.
Timeout
=
DefaultResolverTimeout
...
@@ -92,6 +154,16 @@ func NewResolver(timeout, ttl time.Duration, servers ...NameServer) ReloadResolv
...
@@ -92,6 +154,16 @@ func NewResolver(timeout, ttl time.Duration, servers ...NameServer) ReloadResolv
return
r
return
r
}
}
func
newResolver
(
timeout
,
ttl
time
.
Duration
,
servers
...
NameServer
)
*
resolver
{
return
&
resolver
{
Servers
:
servers
,
Timeout
:
timeout
,
TTL
:
ttl
,
mCache
:
&
sync
.
Map
{},
stopped
:
make
(
chan
struct
{}),
}
}
func
(
r
*
resolver
)
copyServers
()
[]
NameServer
{
func
(
r
*
resolver
)
copyServers
()
[]
NameServer
{
var
servers
[]
NameServer
var
servers
[]
NameServer
for
i
:=
range
r
.
Servers
{
for
i
:=
range
r
.
Servers
{
...
@@ -107,12 +179,11 @@ func (r *resolver) Resolve(host string) (ips []net.IP, err error) {
...
@@ -107,12 +179,11 @@ func (r *resolver) Resolve(host string) (ips []net.IP, err error) {
}
}
var
domain
string
var
domain
string
var
t
imeout
,
t
tl
time
.
Duration
var
ttl
time
.
Duration
var
servers
[]
NameServer
var
servers
[]
NameServer
r
.
mux
.
RLock
()
r
.
mux
.
RLock
()
domain
=
r
.
domain
domain
=
r
.
domain
timeout
=
r
.
Timeout
ttl
=
r
.
TTL
ttl
=
r
.
TTL
servers
=
r
.
copyServers
()
servers
=
r
.
copyServers
()
r
.
mux
.
RUnlock
()
r
.
mux
.
RUnlock
()
...
@@ -133,7 +204,7 @@ func (r *resolver) Resolve(host string) (ips []net.IP, err error) {
...
@@ -133,7 +204,7 @@ func (r *resolver) Resolve(host string) (ips []net.IP, err error) {
}
}
for
_
,
ns
:=
range
servers
{
for
_
,
ns
:=
range
servers
{
ips
,
err
=
r
.
resolve
(
ns
,
host
,
timeou
t
)
ips
,
err
=
r
.
resolve
(
ns
.
exchanger
,
hos
t
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[resolver] %s via %s : %s"
,
host
,
ns
,
err
)
log
.
Logf
(
"[resolver] %s via %s : %s"
,
host
,
ns
,
err
)
continue
continue
...
@@ -151,36 +222,14 @@ func (r *resolver) Resolve(host string) (ips []net.IP, err error) {
...
@@ -151,36 +222,14 @@ func (r *resolver) Resolve(host string) (ips []net.IP, err error) {
return
return
}
}
func
(
*
resolver
)
resolve
(
ns
NameServer
,
host
string
,
timeout
time
.
Duration
)
(
ips
[]
net
.
IP
,
err
error
)
{
func
(
*
resolver
)
resolve
(
ex
Exchanger
,
host
string
)
(
ips
[]
net
.
IP
,
err
error
)
{
addr
:=
ns
.
Addr
if
ex
==
nil
{
if
_
,
port
,
_
:=
net
.
SplitHostPort
(
addr
);
port
==
""
{
return
addr
=
net
.
JoinHostPort
(
addr
,
"53"
)
}
client
:=
dns
.
Client
{
Timeout
:
timeout
,
}
switch
strings
.
ToLower
(
ns
.
Protocol
)
{
case
"tcp"
:
client
.
Net
=
"tcp"
case
"tls"
:
cfg
:=
&
tls
.
Config
{
ServerName
:
ns
.
Hostname
,
}
if
cfg
.
ServerName
==
""
{
cfg
.
InsecureSkipVerify
=
true
}
client
.
Net
=
"tcp-tls"
client
.
TLSConfig
=
cfg
case
"udp"
:
fallthrough
default
:
client
.
Net
=
"udp"
}
}
m
:=
dns
.
Msg
{}
query
:=
dns
.
Msg
{}
m
.
SetQuestion
(
dns
.
Fqdn
(
host
),
dns
.
TypeA
)
query
.
SetQuestion
(
dns
.
Fqdn
(
host
),
dns
.
TypeA
)
mr
,
_
,
err
:=
client
.
Exchange
(
&
m
,
addr
)
mr
,
err
:=
ex
.
Exchange
(
context
.
Background
(),
&
query
)
if
err
!=
nil
{
if
err
!=
nil
{
return
return
}
}
...
@@ -223,7 +272,7 @@ func (r *resolver) Reload(rd io.Reader) error {
...
@@ -223,7 +272,7 @@ func (r *resolver) Reload(rd io.Reader) error {
var
domain
string
var
domain
string
var
nss
[]
NameServer
var
nss
[]
NameServer
if
r
.
Stopped
()
{
if
r
d
==
nil
||
r
.
Stopped
()
{
return
nil
return
nil
}
}
...
@@ -293,7 +342,15 @@ func (r *resolver) Reload(rd io.Reader) error {
...
@@ -293,7 +342,15 @@ func (r *resolver) Reload(rd io.Reader) error {
ns
.
Protocol
=
ss
[
1
]
ns
.
Protocol
=
ss
[
1
]
ns
.
Hostname
=
ss
[
2
]
ns
.
Hostname
=
ss
[
2
]
}
}
nss
=
append
(
nss
,
ns
)
ns
.
Timeout
=
timeout
if
timeout
<=
0
{
ns
.
Timeout
=
DefaultResolverTimeout
}
if
err
:=
ns
.
Init
();
err
==
nil
{
nss
=
append
(
nss
,
ns
)
}
}
}
}
}
...
@@ -359,3 +416,80 @@ func (r *resolver) String() string {
...
@@ -359,3 +416,80 @@ func (r *resolver) String() string {
}
}
return
b
.
String
()
return
b
.
String
()
}
}
// Exchanger is an interface for DNS synchronous query.
type
Exchanger
interface
{
Exchange
(
ctx
context
.
Context
,
query
*
dns
.
Msg
)
(
*
dns
.
Msg
,
error
)
}
type
dnsExchanger
struct
{
endpoint
string
client
*
dns
.
Client
}
func
(
ex
*
dnsExchanger
)
Exchange
(
ctx
context
.
Context
,
query
*
dns
.
Msg
)
(
*
dns
.
Msg
,
error
)
{
ep
:=
ex
.
endpoint
if
_
,
port
,
_
:=
net
.
SplitHostPort
(
ep
);
port
==
""
{
ep
=
net
.
JoinHostPort
(
ep
,
"53"
)
}
mr
,
_
,
err
:=
ex
.
client
.
Exchange
(
query
,
ep
)
return
mr
,
err
}
type
dohExchanger
struct
{
endpoint
*
url
.
URL
client
*
http
.
Client
}
// reference: https://github.com/cloudflare/cloudflared/blob/master/tunneldns/https_upstream.go#L54
func
(
ex
*
dohExchanger
)
Exchange
(
ctx
context
.
Context
,
query
*
dns
.
Msg
)
(
*
dns
.
Msg
,
error
)
{
queryBuf
,
err
:=
query
.
Pack
()
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to pack DNS query: %s"
,
err
)
}
// No content negotiation for now, use DNS wire format
buf
,
backendErr
:=
ex
.
exchangeWireformat
(
queryBuf
)
if
backendErr
==
nil
{
response
:=
&
dns
.
Msg
{}
if
err
:=
response
.
Unpack
(
buf
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to unpack DNS response from body: %s"
,
err
)
}
response
.
Id
=
query
.
Id
return
response
,
nil
}
return
nil
,
backendErr
}
// Perform message exchange with the default UDP wireformat defined in current draft
// https://datatracker.ietf.org/doc/draft-ietf-doh-dns-over-https
func
(
ex
*
dohExchanger
)
exchangeWireformat
(
msg
[]
byte
)
([]
byte
,
error
)
{
req
,
err
:=
http
.
NewRequest
(
"POST"
,
ex
.
endpoint
.
String
(),
bytes
.
NewBuffer
(
msg
))
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to create an HTTPS request: %s"
,
err
)
}
req
.
Header
.
Add
(
"Content-Type"
,
"application/dns-udpwireformat"
)
req
.
Host
=
ex
.
endpoint
.
Hostname
()
resp
,
err
:=
ex
.
client
.
Do
(
req
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to perform an HTTPS request: %s"
,
err
)
}
// Check response status code
defer
resp
.
Body
.
Close
()
if
resp
.
StatusCode
!=
http
.
StatusOK
{
return
nil
,
fmt
.
Errorf
(
"returned status code %d"
,
resp
.
StatusCode
)
}
// Read wireformat response from the body
buf
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to read the response body: %s"
,
err
)
}
return
buf
,
nil
}
resolver_test.go
0 → 100644
View file @
a7d49f0b
package
gost
import
(
"bytes"
"fmt"
"io"
"testing"
"time"
)
var
dnsTests
=
[]
struct
{
ns
NameServer
host
string
pass
bool
}{
{
NameServer
{
Addr
:
"1.1.1.1"
},
"github.com"
,
true
},
{
NameServer
{
Addr
:
"1.1.1.1:53"
},
"github.com"
,
true
},
{
NameServer
{
Addr
:
"1.1.1.1:53"
,
Protocol
:
"tcp"
},
"github.com"
,
true
},
{
NameServer
{
Addr
:
"1.1.1.1:853"
,
Protocol
:
"tls"
},
"github.com"
,
true
},
{
NameServer
{
Addr
:
"1.1.1.1:853"
,
Protocol
:
"tls"
,
Hostname
:
"example.com"
},
"github.com"
,
false
},
{
NameServer
{
Addr
:
"1.1.1.1:853"
,
Protocol
:
"tls"
,
Hostname
:
"cloudflare-dns.com"
},
"github.com"
,
true
},
{
NameServer
{
Addr
:
"https://cloudflare-dns.com/dns-query"
,
Protocol
:
"https"
},
"github.com"
,
true
},
{
NameServer
{
Addr
:
"https://1.0.0.1/dns-query"
,
Protocol
:
"https"
},
"github.com"
,
true
},
{
NameServer
{
Addr
:
"1.1.1.1:12345"
,
Timeout
:
1
*
time
.
Second
},
"github.com"
,
false
},
{
NameServer
{
Addr
:
"1.1.1.1:12345"
,
Protocol
:
"tcp"
,
Timeout
:
1
*
time
.
Second
},
"github.com"
,
false
},
{
NameServer
{
Addr
:
"1.1.1.1:12345"
,
Protocol
:
"tls"
,
Timeout
:
1
*
time
.
Second
},
"github.com"
,
false
},
{
NameServer
{
Addr
:
"https://1.0.0.1:12345/dns-query"
,
Protocol
:
"https"
,
Timeout
:
1
*
time
.
Second
},
"github.com"
,
false
},
}
func
dnsResolverRoundtrip
(
t
*
testing
.
T
,
r
Resolver
,
host
string
)
error
{
ips
,
err
:=
r
.
Resolve
(
host
)
t
.
Log
(
host
,
ips
,
err
)
if
err
!=
nil
{
return
err
}
return
nil
}
func
TestDNSResolver
(
t
*
testing
.
T
)
{
for
i
,
tc
:=
range
dnsTests
{
tc
:=
tc
t
.
Run
(
fmt
.
Sprintf
(
"#%d"
,
i
),
func
(
t
*
testing
.
T
)
{
ns
:=
tc
.
ns
if
err
:=
ns
.
Init
();
err
!=
nil
{
t
.
Error
(
err
)
}
t
.
Log
(
ns
)
r
:=
NewResolver
(
0
,
0
,
ns
)
err
:=
dnsResolverRoundtrip
(
t
,
r
,
tc
.
host
)
if
err
!=
nil
{
if
tc
.
pass
{
t
.
Error
(
"got error:"
,
err
)
}
}
else
{
if
!
tc
.
pass
{
t
.
Error
(
"should failed"
)
}
}
})
}
}
var
resolverReloadTests
=
[]
struct
{
r
io
.
Reader
timeout
time
.
Duration
ttl
time
.
Duration
domain
string
period
time
.
Duration
ns
*
NameServer
stopped
bool
}{
{
r
:
nil
,
},
{
r
:
bytes
.
NewBufferString
(
""
),
},
{
r
:
bytes
.
NewBufferString
(
"reload 10s"
),
period
:
10
*
time
.
Second
,
},
{
r
:
bytes
.
NewBufferString
(
"timeout 10s
\n
reload 10s
\n
"
),
timeout
:
10
*
time
.
Second
,
period
:
10
*
time
.
Second
,
},
{
r
:
bytes
.
NewBufferString
(
"ttl 10s
\n
timeout 10s
\n
reload 10s
\n
"
),
timeout
:
10
*
time
.
Second
,
period
:
10
*
time
.
Second
,
ttl
:
10
*
time
.
Second
,
},
{
r
:
bytes
.
NewBufferString
(
"domain example.com
\n
ttl 10s
\n
timeout 10s
\n
reload 10s
\n
"
),
timeout
:
10
*
time
.
Second
,
period
:
10
*
time
.
Second
,
ttl
:
10
*
time
.
Second
,
domain
:
"example.com"
,
},
{
r
:
bytes
.
NewBufferString
(
"1.1.1.1"
),
ns
:
&
NameServer
{
Addr
:
"1.1.1.1"
,
Timeout
:
DefaultResolverTimeout
,
},
stopped
:
true
,
},
{
r
:
bytes
.
NewBufferString
(
"timeout 10s
\n
search
\n
nameserver
\n
nameserver 1.1.1.1 udp"
),
ns
:
&
NameServer
{
Protocol
:
"udp"
,
Addr
:
"1.1.1.1"
,
Timeout
:
10
*
time
.
Second
,
},
timeout
:
10
*
time
.
Second
,
stopped
:
true
,
},
{
r
:
bytes
.
NewBufferString
(
"1.1.1.1 tcp"
),
ns
:
&
NameServer
{
Addr
:
"1.1.1.1"
,
Protocol
:
"tcp"
,
Timeout
:
DefaultResolverTimeout
,
},
stopped
:
true
,
},
{
r
:
bytes
.
NewBufferString
(
"1.1.1.1:853 tls cloudflare-dns.com"
),
ns
:
&
NameServer
{
Addr
:
"1.1.1.1:853"
,
Protocol
:
"tls"
,
Hostname
:
"cloudflare-dns.com"
,
Timeout
:
DefaultResolverTimeout
,
},
stopped
:
true
,
},
{
r
:
bytes
.
NewBufferString
(
"1.1.1.1:853 tls"
),
ns
:
&
NameServer
{
Addr
:
"1.1.1.1:853"
,
Protocol
:
"tls"
,
Timeout
:
DefaultResolverTimeout
,
},
stopped
:
true
,
},
{
r
:
bytes
.
NewBufferString
(
"1.0.0.1:53 https"
),
stopped
:
true
,
},
{
r
:
bytes
.
NewBufferString
(
"https://1.0.0.1/dns-query https"
),
ns
:
&
NameServer
{
Addr
:
"https://1.0.0.1/dns-query"
,
Protocol
:
"https"
,
Timeout
:
DefaultResolverTimeout
,
},
stopped
:
true
,
},
}
func
TestResolverReload
(
t
*
testing
.
T
)
{
for
i
,
tc
:=
range
resolverReloadTests
{
t
.
Run
(
fmt
.
Sprintf
(
"#%d"
,
i
),
func
(
t
*
testing
.
T
)
{
r
:=
newResolver
(
0
,
0
)
if
err
:=
r
.
Reload
(
tc
.
r
);
err
!=
nil
{
t
.
Error
(
err
)
}
t
.
Log
(
r
.
String
())
if
r
.
Timeout
!=
tc
.
timeout
{
t
.
Errorf
(
"timeout value should be %v, got %v"
,
tc
.
timeout
,
r
.
Timeout
)
}
if
r
.
TTL
!=
tc
.
ttl
{
t
.
Errorf
(
"ttl value should be %v, got %v"
,
tc
.
ttl
,
r
.
TTL
)
}
if
r
.
Period
()
!=
tc
.
period
{
t
.
Errorf
(
"period value should be %v, got %v"
,
tc
.
period
,
r
.
period
)
}
if
r
.
domain
!=
tc
.
domain
{
t
.
Errorf
(
"domain value should be %v, got %v"
,
tc
.
domain
,
r
.
domain
)
}
var
ns
*
NameServer
if
len
(
r
.
Servers
)
>
0
{
ns
=
&
r
.
Servers
[
0
]
}
if
!
compareNameServer
(
ns
,
tc
.
ns
)
{
t
.
Errorf
(
"nameserver not equal, should be %v, got %v"
,
tc
.
ns
,
r
.
Servers
)
}
if
tc
.
stopped
{
r
.
Stop
()
}
if
r
.
Stopped
()
!=
tc
.
stopped
{
t
.
Errorf
(
"stopped value should be %v, got %v"
,
tc
.
stopped
,
r
.
Stopped
())
}
})
}
}
func
compareNameServer
(
n1
,
n2
*
NameServer
)
bool
{
if
n1
==
n2
{
return
true
}
if
n1
==
nil
||
n2
==
nil
{
return
false
}
return
n1
.
Addr
==
n2
.
Addr
&&
n1
.
Hostname
==
n2
.
Hostname
&&
n1
.
Protocol
==
n2
.
Protocol
&&
n1
.
Timeout
==
n2
.
Timeout
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment