Skip to content

Commit

Permalink
doc: improve code comments on dns resolution logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Stebalien committed Sep 19, 2019
1 parent 8c560f5 commit 0eb9e18
Showing 1 changed file with 51 additions and 5 deletions.
56 changes: 51 additions & 5 deletions resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ func (r *Resolver) Resolve(ctx context.Context, maddr ma.Multiaddr) ([]ma.Multia
var results []ma.Multiaddr
for i := 0; maddr != nil; i++ {
var keep ma.Multiaddr

// Find the next dns component.
keep, maddr = ma.SplitFunc(maddr, func(c ma.Component) bool {
switch c.Protocol().Code {
case DnsProtocol.Code, Dns4Protocol.Code, Dns6Protocol.Code, DnsaddrProtocol.Code:
Expand All @@ -73,31 +75,36 @@ func (r *Resolver) Resolve(ctx context.Context, maddr ma.Multiaddr) ([]ma.Multia
}
})

// Append the part we're keeping.
// Keep everything before the dns component.
if keep != nil {
if results == nil {
results = append(results, keep)
if len(results) == 0 {
results = []ma.Multiaddr{keep}
} else {
for i, r := range results {
results[i] = r.Encapsulate(keep)
}
}
}

// Check to see if we're done.
// If the rest is empty, we've hit the end (there _was_ no dns component).
if maddr == nil {
break
}

// split off the dns component.
var resolve *ma.Component
resolve, maddr = ma.SplitFirst(maddr)

proto := resolve.Protocol()
value := resolve.Value()

// resolve the dns component
var resolved []ma.Multiaddr
switch proto.Code {
case Dns4Protocol.Code, Dns6Protocol.Code, DnsProtocol.Code:
// The dns, dns4, and dns6 resolver simply resolves each
// dns* component into an ipv4/ipv6 address.

v4only := proto.Code == Dns4Protocol.Code
v6only := proto.Code == Dns6Protocol.Code

Expand All @@ -110,6 +117,10 @@ func (r *Resolver) Resolve(ctx context.Context, maddr ma.Multiaddr) ([]ma.Multia
return nil, err
}

// Convert each DNS record into a multiaddr. If the
// protocol is dns4, throw away any IPv6 addresses. If
// the protocol is dns6, throw away any IPv4 addresses.

for _, r := range records {
var (
rmaddr ma.Multiaddr
Expand All @@ -133,27 +144,47 @@ func (r *Resolver) Resolve(ctx context.Context, maddr ma.Multiaddr) ([]ma.Multia
resolved = append(resolved, rmaddr)
}
case DnsaddrProtocol.Code:
// The dnsaddr resolver is a bit more complicated. We:
//
// 1. Lookup the dnsaddr txt record on _dnsaddr.DOMAIN.TLD
// 2. Take everything _after_ the `/dnsaddr/DOMAIN.TLD`
// part of the multiaddr.
// 3. Find the dnsaddr records (if any) with suffixes
// matching the result of step 2.

// First, lookup the TXT record
records, err := r.Backend.LookupTXT(ctx, "_dnsaddr."+value)
if err != nil {
return nil, err
}

// Then, calculate the length of the suffix we're
// looking for.
length := 0
if maddr != nil {
length = addrLen(maddr)
}

for _, r := range records {
// Ignore non dnsaddr TXT records.
if !strings.HasPrefix(r, dnsaddrTXTPrefix) {
continue
}

// Extract and decode the multiaddr.
rmaddr, err := ma.NewMultiaddr(r[len(dnsaddrTXTPrefix):])
if err != nil {
// discard multiaddrs we don't understand.
// XXX: Is this right?
// XXX: Is this right? It's the best we
// can do for now, really.
continue
}

// If we have a suffix to match on.
if maddr != nil {
// Make sure the new address is at least
// as long as the suffix we're looking
// for.
rmlen := addrLen(rmaddr)
if rmlen < length {
// not long enough.
Expand Down Expand Up @@ -186,12 +217,23 @@ func (r *Resolver) Resolve(ctx context.Context, maddr ma.Multiaddr) ([]ma.Multia
} else if len(results) == 0 {
results = resolved
} else {
// We take the cross product here as we don't have any
// better way to represent "ORs" in multiaddrs. For
// example, `/dns/foo.com/p2p-circuit/dns/bar.com` could
// resolve to:
//
// * /ip4/1.1.1.1/p2p-circuit/ip4/2.1.1.1
// * /ip4/1.1.1.1/p2p-circuit/ip4/2.1.1.2
// * /ip4/1.1.1.2/p2p-circuit/ip4/2.1.1.1
// * /ip4/1.1.1.2/p2p-circuit/ip4/2.1.1.2
results = cross(results, resolved)
}
}

return results, nil
}

// counts the number of components in the multiaddr
func addrLen(maddr ma.Multiaddr) int {
length := 0
ma.ForEach(maddr, func(_ ma.Component) bool {
Expand All @@ -201,6 +243,7 @@ func addrLen(maddr ma.Multiaddr) int {
return length
}

// trims `offset` components from the beginning of the multiaddr.
func offset(maddr ma.Multiaddr, offset int) ma.Multiaddr {
_, after := ma.SplitFunc(maddr, func(c ma.Component) bool {
if offset == 0 {
Expand All @@ -212,6 +255,9 @@ func offset(maddr ma.Multiaddr, offset int) ma.Multiaddr {
return after
}

// takes the cross product of two sets of multiaddrs
//
// assumes `a` is non-empty.
func cross(a, b []ma.Multiaddr) []ma.Multiaddr {
res := make([]ma.Multiaddr, 0, len(a)*len(b))
for _, x := range a {
Expand Down

0 comments on commit 0eb9e18

Please sign in to comment.