Skip to content

Commit

Permalink
fix(swarm): add dnsaddr support in swarm connect
Browse files Browse the repository at this point in the history
License: MIT
Signed-off-by: Overbool <overbool.xu@gmail.com>
  • Loading branch information
overbool committed Oct 5, 2018
1 parent ab9e211 commit a448431
Showing 1 changed file with 98 additions and 14 deletions.
112 changes: 98 additions & 14 deletions core/commands/swarm.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package commands

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

"github.com/ipfs/go-ipfs/commands"
"github.com/ipfs/go-ipfs/core/commands/cmdenv"
"github.com/ipfs/go-ipfs/core/commands/e"
"github.com/ipfs/go-ipfs/repo"
"github.com/ipfs/go-ipfs/repo/fsrepo"
commands "github.com/ipfs/go-ipfs/commands"
cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
e "github.com/ipfs/go-ipfs/core/commands/e"
repo "github.com/ipfs/go-ipfs/repo"
fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"

inet "gx/ipfs/QmQdLcvoy3JuSqhV6iwQ9T6Cv7hWLAdzob4jUZRPqFL67Z/go-libp2p-net"
pstore "gx/ipfs/QmSJ36wcYQyEViJUWUEhJU81tw1KdakTKqLLHbvYbA9zDv/go-libp2p-peerstore"
Expand All @@ -24,6 +27,11 @@ import (
peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer"
"gx/ipfs/QmcALnLPFXgLLaZkXzGv99yt8xPfiWqFTumiXpWBJbU9cY/go-libp2p-swarm"
iaddr "gx/ipfs/QmesXvbRGyKQn1XbPHx1Mr5E6RTJYR9c8zwFVuGZq9Aa1j/go-ipfs-addr"
madns "gx/ipfs/QmfXU2MhWoegxHoeMd3A2ytL2P6CY4FfqGWc23LTNWBwZt/go-multiaddr-dns"
)

const (
dnsResolveTimeout = 10 * time.Second
)

type stringList struct {
Expand Down Expand Up @@ -52,6 +60,13 @@ ipfs peers in the internet.
},
}

const (
swarmVerboseOptionName = "verbose"
swarmStreamsOptionName = "streams"
swarmLatencyOptionName = "latency"
swarmDirectionOptionName = "direction"
)

var swarmPeersCmd = &cmds.Command{
Helptext: cmdkit.HelpText{
Tagline: "List peers with open connections.",
Expand All @@ -60,21 +75,21 @@ var swarmPeersCmd = &cmds.Command{
`,
},
Options: []cmdkit.Option{
cmdkit.BoolOption("verbose", "v", "display all extra information"),
cmdkit.BoolOption("streams", "Also list information about open streams for each peer"),
cmdkit.BoolOption("latency", "Also list information about latency to each peer"),
cmdkit.BoolOption("direction", "Also list information about the direction of connection"),
cmdkit.BoolOption(swarmVerboseOptionName, "v", "display all extra information"),
cmdkit.BoolOption(swarmStreamsOptionName, "Also list information about open streams for each peer"),
cmdkit.BoolOption(swarmLatencyOptionName, "Also list information about latency to each peer"),
cmdkit.BoolOption(swarmDirectionOptionName, "Also list information about the direction of connection"),
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
api, err := cmdenv.GetApi(env)
if err != nil {
return err
}

verbose, _ := req.Options["verbose"].(bool)
latency, _ := req.Options["latency"].(bool)
streams, _ := req.Options["streams"].(bool)
direction, _ := req.Options["direction"].(bool)
verbose, _ := req.Options[swarmVerboseOptionName].(bool)
latency, _ := req.Options[swarmLatencyOptionName].(bool)
streams, _ := req.Options[swarmStreamsOptionName].(bool)
direction, _ := req.Options[swarmDirectionOptionName].(bool)

conns, err := api.Swarm().Peers(req.Context)
if err != nil {
Expand Down Expand Up @@ -453,10 +468,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)
// resolve addresses
maddrs, err := resolveAddresses(addrs)
if err != nil {
return nil, err
}

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

// resolveAddresses resolves addresses parallelly
func resolveAddresses(addrs []string) ([]ma.Multiaddr, error) {
var maddrs []ma.Multiaddr
var wg sync.WaitGroup
resolveErrC := make(chan error, len(addrs))

for _, addr := range addrs {
maddr, err := ma.NewMultiaddr(addr)
if err != nil {
return nil, err
}
// check whether address ends in `ipfs/Qm...`
if _, err := maddr.ValueForProtocol(ma.P_IPFS); err != ma.ErrProtocolNotFound {
maddrs = append(maddrs, maddr)
continue
}
wg.Add(1)
go func(maddr ma.Multiaddr) {
defer wg.Done()
ctx, cancel := context.WithTimeout(context.Background(), dnsResolveTimeout)
raddrs, err := madns.Resolve(ctx, maddr)
cancel()
if err != nil {
resolveErrC <- err
return
}
if len(raddrs) == 0 {
resolveErrC <- fmt.Errorf("non-resolvable multiaddr about %v", maddr)
return
}
// filter out addresses that still doesn't end in `ipfs/Qm...`
for _, raddr := range raddrs {
if _, err := raddr.ValueForProtocol(ma.P_IPFS); err != ma.ErrProtocolNotFound {
maddrs = append(maddrs, raddr)
}
}
}(maddr)
}
// wait for address resolving
wg.Wait()

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

return maddrs, nil
}

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

0 comments on commit a448431

Please sign in to comment.