Skip to content

Commit

Permalink
Create a separate dns package.
Browse files Browse the repository at this point in the history
  • Loading branch information
9seconds committed Dec 8, 2020
1 parent b1012b1 commit 15b33d6
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 16 deletions.
13 changes: 2 additions & 11 deletions dialers/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"time"

"github.com/9seconds/httransform/v2/cache"
"github.com/9seconds/httransform/v2/dns"
"github.com/libp2p/go-reuseport"
"github.com/valyala/fasthttp"
)
Expand All @@ -21,17 +22,10 @@ const (

// TLSConfigTTL defines a TTL for each tls.Config we generate.
TLSConfigTTL = 10 * time.Minute

// DNSCacheSize defines a size of cache for DNS entries.
DNSCacheSize = 512

// DNSCacheTTL defines a TTL for each DNS entry.
DNSCacheTTL = 5 * time.Minute
)

type base struct {
netDialer net.Dialer
dns dnsCache
tlsConfigsLock sync.Mutex
tlsConfigs cache.Interface
tlsSkipVerify bool
Expand All @@ -41,7 +35,7 @@ func (b *base) Dial(ctx context.Context, host, port string) (net.Conn, error) {
ctx, cancel := context.WithTimeout(ctx, b.netDialer.Timeout)
defer cancel()

ips, err := b.dns.Lookup(ctx, host)
ips, err := dns.Default.Lookup(ctx, host)
if err != nil {
return nil, fmt.Errorf("cannot resolve IPs: %w", err)
}
Expand Down Expand Up @@ -142,9 +136,6 @@ func NewBase(opt Opts) Dialer {
Timeout: opt.GetTimeout(),
Control: reuseport.Control,
},
dns: dnsCache{
cache: cache.New(DNSCacheSize, DNSCacheTTL, cache.NoopEvictCallback),
},
tlsConfigs: cache.New(TLSConfigCacheSize,
TLSConfigTTL,
cache.NoopEvictCallback),
Expand Down
20 changes: 15 additions & 5 deletions dialers/dns.go → dns/dns.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
package dialers
package dns

import (
"context"
"fmt"
"net"
"time"

"github.com/9seconds/httransform/v2/cache"
"github.com/valyala/fastrand"
)

type dnsCache struct {
// DNS is a caching resolver.
type DNS struct {
resolver net.Resolver
cache cache.Interface
}

func (d *dnsCache) Lookup(ctx context.Context, hostname string) (hosts []string, err error) {
// Lookup to conform Interface.
func (d *DNS) Lookup(ctx context.Context, hostname string) (hosts []string, err error) {
if hh := d.cache.Get(hostname); hh != nil {
hosts = hh.([]string)
} else {
Expand All @@ -30,7 +33,7 @@ func (d *dnsCache) Lookup(ctx context.Context, hostname string) (hosts []string,
return d.shuffle(hosts), nil
}

func (d *dnsCache) doLookup(ctx context.Context, hostname string) ([]string, error) {
func (d *DNS) doLookup(ctx context.Context, hostname string) ([]string, error) {
if net.ParseIP(hostname) == nil {
return d.resolver.LookupHost(ctx, hostname)
}
Expand All @@ -49,7 +52,7 @@ func (d *dnsCache) doLookup(ctx context.Context, hostname string) ([]string, err
return hostnames, nil
}

func (d *dnsCache) shuffle(in []string) []string {
func (d *DNS) shuffle(in []string) []string {
if len(in) < 2 { // nolint: gomnd
return in
}
Expand All @@ -69,3 +72,10 @@ func (d *dnsCache) shuffle(in []string) []string {

return out
}

// New returns a new instance of DNS cache.
func New(cacheSize int, cacheTTL time.Duration, evictCallback cache.EvictCallback) Interface {
return &DNS{
cache: cache.New(cacheSize, cacheTTL, evictCallback),
}
}
46 changes: 46 additions & 0 deletions dns/dns_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package dns_test

import (
"context"
"testing"

"github.com/9seconds/httransform/v2/cache"
"github.com/9seconds/httransform/v2/dns"
"github.com/stretchr/testify/suite"
)

type DNSTestSuite struct {
suite.Suite

cache dns.Interface
}

func (suite *DNSTestSuite) SetupTest() {
suite.cache = dns.New(dns.CacheSize, dns.CacheTTL, cache.NoopEvictCallback)
}

func (suite *DNSTestSuite) TestResolveNames() {
ctx := context.Background()
names, err := suite.cache.Lookup(ctx, "google.com")

suite.NoError(err)

names2, err := suite.cache.Lookup(ctx, "google.com")

suite.NoError(err)

suite.NotEqual(names, names2)
suite.ElementsMatch(names, names2)
}

func (suite *DNSTestSuite) TestResolveIP() {
ctx := context.Background()
names, err := suite.cache.Lookup(ctx, "64.233.165.102")

suite.NoError(err)
suite.NotEmpty(names)
}

func TestDNS(t *testing.T) {
suite.Run(t, &DNSTestSuite{})
}
4 changes: 4 additions & 0 deletions dns/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Cachning DNS resolver.
//
// This package has a global instance of caching DNS service.
package dns
18 changes: 18 additions & 0 deletions dns/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package dns

import (
"time"

"github.com/9seconds/httransform/v2/cache"
)

const (
// CacheSize is a size of DNS cache.
CacheSize = 512

// CacheTTL is a TTL of a DNS record in a cache.
CacheTTL = 5 * time.Minute
)

// Default is a default DNS resolver you usually want to use everywhere.
var Default Interface = New(CacheSize, CacheTTL, cache.NoopEvictCallback)
11 changes: 11 additions & 0 deletions dns/interfaces.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dns

import "context"

// Interface is an interface for cachind DNS resolver.
type Interface interface {
// Lookup returns resolved IPs for given hostname/ips. Important
// property is that this list is shuffled on each function
// execution.
Lookup(context.Context, string) ([]string, error)
}

0 comments on commit 15b33d6

Please sign in to comment.