Skip to content
This repository has been archived by the owner on Jun 20, 2023. It is now read-only.

Commit

Permalink
Merge pull request #10 from ipfs/feat/custom-resolver
Browse files Browse the repository at this point in the history
make DNS resolver pluggable
  • Loading branch information
Stebalien authored Apr 23, 2021
2 parents 22432d1 + df97fc2 commit 2454122
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 151 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
Package namesys defines `Resolver` and `Publisher` interfaces for IPNS paths, that is, paths in the form of `/ipns/<name_to_be_resolved>`. A "resolved" IPNS path becomes an `/ipfs/<cid>` path.

Traditionally, these paths would be in the form of `/ipns/peer_id`, which references an IPNS record in a distributed `ValueStore` (usually the IPFS DHT).
Traditionally, these paths would be in the form of `/ipns/{libp2p-key}`, which references an IPNS record in a distributed `ValueStore` (usually the IPFS DHT).

Additionally, the /ipns/ namespace can also be used with domain names that use DNSLink (/ipns/my.domain.example, see https://dnslink.io) and proquint strings.
Additionally, the `/ipns/` namespace can also be used with domain names that use DNSLink (`/ipns/en.wikipedia-on-ipfs.org`, see https://docs.ipfs.io/concepts/dnslink/).

The package provides implementations for all three resolvers.

Expand Down
29 changes: 10 additions & 19 deletions dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,11 @@ import (

path "github.com/ipfs/go-path"
opts "github.com/ipfs/interface-go-ipfs-core/options/namesys"
isd "github.com/jbenet/go-is-domain"
dns "github.com/miekg/dns"
)

const ethTLD = "eth"
const linkTLD = "domains"

// LookupTXTFunc is a generic type for a function that lookups TXT record values.
type LookupTXTFunc func(name string) (txt []string, err error)
// LookupTXTFunc is a function that lookups TXT record values.
type LookupTXTFunc func(ctx context.Context, name string) (txt []string, err error)

// DNSResolver implements a Resolver on DNS domains
type DNSResolver struct {
Expand All @@ -27,8 +24,8 @@ type DNSResolver struct {
}

// NewDNSResolver constructs a name resolver using DNS TXT records.
func NewDNSResolver() *DNSResolver {
return &DNSResolver{lookupTXT: net.LookupTXT}
func NewDNSResolver(lookup LookupTXTFunc) *DNSResolver {
return &DNSResolver{lookupTXT: lookup}
}

// Resolve implements Resolver.
Expand All @@ -55,7 +52,7 @@ func (r *DNSResolver) resolveOnceAsync(ctx context.Context, name string, options
segments := strings.SplitN(name, "/", 2)
domain := segments[0]

if !isd.IsDomain(domain) {
if _, ok := dns.IsDomainName(domain); !ok {
out <- onceResult{err: fmt.Errorf("not a valid domain name: %s", domain)}
close(out)
return out
Expand All @@ -68,17 +65,11 @@ func (r *DNSResolver) resolveOnceAsync(ctx context.Context, name string, options
fqdn = domain + "."
}

if strings.HasSuffix(fqdn, "."+ethTLD+".") {
// This is an ENS name. As we're resolving via an arbitrary DNS server
// that may not know about .eth we need to add our link domain suffix.
fqdn += linkTLD + "."
}

rootChan := make(chan lookupRes, 1)
go workDomain(r, fqdn, rootChan)
go workDomain(ctx, r, fqdn, rootChan)

subChan := make(chan lookupRes, 1)
go workDomain(r, "_dnslink."+fqdn, subChan)
go workDomain(ctx, r, "_dnslink."+fqdn, subChan)

appendPath := func(p path.Path) (path.Path, error) {
if len(segments) > 1 {
Expand Down Expand Up @@ -139,10 +130,10 @@ func (r *DNSResolver) resolveOnceAsync(ctx context.Context, name string, options
return out
}

func workDomain(r *DNSResolver, name string, res chan lookupRes) {
func workDomain(ctx context.Context, r *DNSResolver, name string, res chan lookupRes) {
defer close(res)

txt, err := r.lookupTXT(name)
txt, err := r.lookupTXT(ctx, name)
if err != nil {
if dnsErr, ok := err.(*net.DNSError); ok {
// If no TXT records found, return same error as when no text
Expand Down
19 changes: 16 additions & 3 deletions dns_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package namesys

import (
"context"
"fmt"
"testing"

Expand All @@ -11,7 +12,7 @@ type mockDNS struct {
entries map[string][]string
}

func (m *mockDNS) lookupTXT(name string) (txt []string, err error) {
func (m *mockDNS) lookupTXT(ctx context.Context, name string) (txt []string, err error) {
txt, ok := m.entries[name]
if !ok {
return nil, fmt.Errorf("no TXT entry for %s", name)
Expand Down Expand Up @@ -126,7 +127,16 @@ func newMockDNS() *mockDNS {
"fqdn.example.com.": {
"dnslink=/ipfs/QmYvMB9yrsSf7RKBghkfwmHJkzJhW2ZgVwq3LxBXXPasFr",
},
"www.wealdtech.eth.domains.": {
"en.wikipedia-on-ipfs.org.": {
"dnslink=/ipfs/bafybeiaysi4s6lnjev27ln5icwm6tueaw2vdykrtjkwiphwekaywqhcjze",
},
"custom.non-icann.tldextravaganza.": {
"dnslink=/ipfs/bafybeieto6mcuvqlechv4iadoqvnffondeiwxc2bcfcewhvpsd2odvbmvm",
},
"singlednslabelshouldbeok.": {
"dnslink=/ipfs/bafybeih4a6ylafdki6ailjrdvmr7o4fbbeceeeuty4v3qyyouiz5koqlpi",
},
"www.wealdtech.eth.": {
"dnslink=/ipns/ipfs.example.com",
},
},
Expand Down Expand Up @@ -166,7 +176,10 @@ func TestDNSResolution(t *testing.T) {
testResolution(t, r, "double.example.com", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
testResolution(t, r, "conflict.example.com", opts.DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjE", nil)
testResolution(t, r, "fqdn.example.com.", opts.DefaultDepthLimit, "/ipfs/QmYvMB9yrsSf7RKBghkfwmHJkzJhW2ZgVwq3LxBXXPasFr", nil)
testResolution(t, r, "en.wikipedia-on-ipfs.org", 2, "/ipfs/bafybeiaysi4s6lnjev27ln5icwm6tueaw2vdykrtjkwiphwekaywqhcjze", nil)
testResolution(t, r, "custom.non-icann.tldextravaganza.", 2, "/ipfs/bafybeieto6mcuvqlechv4iadoqvnffondeiwxc2bcfcewhvpsd2odvbmvm", nil)
testResolution(t, r, "singlednslabelshouldbeok", 2, "/ipfs/bafybeih4a6ylafdki6ailjrdvmr7o4fbbeceeeuty4v3qyyouiz5koqlpi", nil)
testResolution(t, r, "www.wealdtech.eth", 1, "/ipns/ipfs.example.com", ErrResolveRecursion)
testResolution(t, r, "www.wealdtech.eth", 2, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
testResolution(t, r, "www.wealdtech.eth.domains", 2, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
testResolution(t, r, "www.wealdtech.eth", 2, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
}
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
module github.com/ipfs/go-namesys

require (
github.com/bren2010/proquint v0.0.0-20160323162903-38337c27106d
github.com/gogo/protobuf v1.3.2
github.com/hashicorp/golang-lru v0.5.4
github.com/ipfs/go-cid v0.0.7
Expand All @@ -13,15 +12,16 @@ require (
github.com/ipfs/go-log v1.0.4
github.com/ipfs/go-path v0.0.9
github.com/ipfs/interface-go-ipfs-core v0.4.0
github.com/jbenet/go-is-domain v1.0.5
github.com/jbenet/goprocess v0.1.4
github.com/libp2p/go-libp2p v0.13.0
github.com/libp2p/go-libp2p-core v0.8.0
github.com/libp2p/go-libp2p-kad-dht v0.11.1
github.com/libp2p/go-libp2p-peerstore v0.2.6
github.com/libp2p/go-libp2p-record v0.1.3
github.com/libp2p/go-libp2p-testing v0.4.0
github.com/miekg/dns v1.1.41
github.com/multiformats/go-multiaddr v0.3.1
github.com/multiformats/go-multiaddr-dns v0.3.1
github.com/multiformats/go-multihash v0.0.14
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc
)
Expand Down
Loading

0 comments on commit 2454122

Please sign in to comment.