Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(swarm): add dnsaddr support in swarm connect #5535

Merged
merged 6 commits into from
Mar 19, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 91 additions & 3 deletions core/commands/swarm.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package commands

import (
"context"
"errors"
"fmt"
"io"
"path"
"sort"
"sync"
"time"

commands "github.com/ipfs/go-ipfs/commands"
cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
Expand All @@ -21,9 +24,14 @@ import (
pstore "github.com/libp2p/go-libp2p-peerstore"
swarm "github.com/libp2p/go-libp2p-swarm"
ma "github.com/multiformats/go-multiaddr"
madns "github.com/multiformats/go-multiaddr-dns"
mafilter "github.com/whyrusleeping/multiaddr-filter"
)

const (
dnsResolveTimeout = 10 * time.Second
)

type stringList struct {
Strings []string
}
Expand Down Expand Up @@ -362,7 +370,7 @@ ipfs swarm connect /ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3

addrs := req.Arguments

pis, err := peersWithAddresses(addrs)
pis, err := peersWithAddresses(req.Context, addrs)
if err != nil {
return err
}
Expand Down Expand Up @@ -444,10 +452,29 @@ func parseAddresses(addrs []string) (iaddrs []iaddr.IPFSAddr, err error) {
return
}

// parseMultiaddrs is a function that takes in a slice of peer multiaddr
// and returns slices of multiaddrs and peerids
func parseMultiaddrs(maddrs []ma.Multiaddr) (iaddrs []iaddr.IPFSAddr, err error) {
iaddrs = make([]iaddr.IPFSAddr, len(maddrs))
for i, maddr := range maddrs {
iaddrs[i], err = iaddr.ParseMultiaddr(maddr)
if err != nil {
return nil, cmds.ClientError("invalid peer address: " + err.Error())
}
}
return
}

// peersWithAddresses is a function that takes in a slice of string peer addresses
// (multiaddr + peerid) and returns a slice of properly constructed peers
func peersWithAddresses(addrs []string) ([]pstore.PeerInfo, error) {
iaddrs, err := parseAddresses(addrs)
func peersWithAddresses(ctx context.Context, addrs []string) ([]pstore.PeerInfo, error) {
// resolve addresses
maddrs, err := resolveAddresses(ctx, addrs)
if err != nil {
return nil, err
}

iaddrs, err := parseMultiaddrs(maddrs)
if err != nil {
return nil, err
}
Expand All @@ -472,6 +499,67 @@ func peersWithAddresses(addrs []string) ([]pstore.PeerInfo, error) {
return pis, nil
}

// resolveAddresses resolves addresses parallelly
func resolveAddresses(ctx context.Context, addrs []string) ([]ma.Multiaddr, error) {
ctx, cancel := context.WithTimeout(ctx, dnsResolveTimeout)
defer cancel()

var maddrs []ma.Multiaddr
var wg sync.WaitGroup
resolveErrC := make(chan error, len(addrs))

maddrC := make(chan ma.Multiaddr)

for _, addr := range addrs {
maddr, err := ma.NewMultiaddr(addr)
if err != nil {
return nil, err
}

// check whether address ends in `ipfs/Qm...`
if _, last := ma.SplitLast(maddr); last.Protocol().Code == ma.P_IPFS {
maddrs = append(maddrs, maddr)
continue
}
wg.Add(1)
go func(maddr ma.Multiaddr) {
defer wg.Done()
raddrs, err := madns.Resolve(ctx, maddr)
if err != nil {
resolveErrC <- err
return
}
// filter out addresses that still doesn't end in `ipfs/Qm...`
found := 0
for _, raddr := range raddrs {
if _, last := ma.SplitLast(raddr); last.Protocol().Code == ma.P_IPFS {
maddrC <- raddr
found++
}
}
if found == 0 {
resolveErrC <- fmt.Errorf("found no ipfs peers at %s", maddr)
}
}(maddr)
}
go func() {
wg.Wait()
close(maddrC)
}()

for maddr := range maddrC {
maddrs = append(maddrs, maddr)
}

select {
case err := <-resolveErrC:
return nil, err
default:
}

return maddrs, nil
}

var swarmFiltersCmd = &cmds.Command{
Helptext: cmdkit.HelpText{
Tagline: "Manipulate address filters.",
Expand Down