fix(swarm): add dnsaddr support in swarm connect
License: MIT Signed-off-by: Overbool <overbool.xu@gmail.com>
Overbool committed
Oct 5, 2018 at 13:12 UTC
309cf70570bd5b7b614e9718c4f0c38c3595f050
1 file changed
+78
-1
core/commands/swarm.go
+78
-1
@@ -1,11 +1,15 @@
1
package commands
2
3
import (
4
+ "context"
5
"errors"
6
"fmt"
7
"io"
8
"path"
9
"sort"
10
+ "strings"
11
+ "sync"
12
+ "time"
13
14
commands "github.com/ipfs/go-ipfs/commands"
15
cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
@@ -24,6 +28,10 @@ import (
28
mafilter "github.com/whyrusleeping/multiaddr-filter"
29
)
30
31
+const (
32
+ dnsResolveTimeout = 10 * time.Second
33
+)
34
+
35
type stringList struct {
36
Strings []string
37
}
@@ -444,10 +452,29 @@ func parseAddresses(addrs []string) (iaddrs []iaddr.IPFSAddr, err error) {
452
return
453
}
454
455
+// parseMultiaddrs is a function that takes in a slice of peer multiaddr
456
+// and returns slices of multiaddrs and peerids
457
+func parseMultiaddrs(maddrs []ma.Multiaddr) (iaddrs []iaddr.IPFSAddr, err error) {
458
+ iaddrs = make([]iaddr.IPFSAddr, len(maddrs))
459
+ for i, maddr := range maddrs {
460
+ iaddrs[i], err = iaddr.ParseMultiaddr(maddr)
461
+ if err != nil {
462
+ return nil, cmds.ClientError("invalid peer address: " + err.Error())
463
+ }
464
+ }
465
+ return
466
+}
467
+
468
// peersWithAddresses is a function that takes in a slice of string peer addresses
469
// (multiaddr + peerid) and returns a slice of properly constructed peers
470
func peersWithAddresses(addrs []string) ([]pstore.PeerInfo, error) {
450
- iaddrs, err := parseAddresses(addrs)
471
+ // resolve addresses
472
+ maddrs, err := resolveAddresses(addrs)
473
+ if err != nil {
474
+ return nil, err
475
+ }
476
+
477
+ iaddrs, err := parseMultiaddrs(maddrs)
478
if err != nil {
479
return nil, err
480
}
@@ -472,6 +499,56 @@ func peersWithAddresses(addrs []string) ([]pstore.PeerInfo, error) {
499
return pis, nil
500
}
501
502
+// resolveAddresses resolves addresses parallelly
503
+func resolveAddresses(addrs []string) ([]ma.Multiaddr, error) {
504
+ var maddrs []ma.Multiaddr
505
+ var wg sync.WaitGroup
506
+ resolveErrC := make(chan error, len(addrs))
507
+
508
+ for _, addr := range addrs {
509
+ maddr, err := ma.NewMultiaddr(addr)
510
+ if err != nil {
511
+ return nil, err
512
+ }
513
+ // check whether address ends in `ipfs/Qm...`
514
+ if _, err := maddr.ValueForProtocol(ma.P_IPFS); err != ma.ErrProtocolNotFound {
515
+ maddrs = append(maddrs, maddr)
516
+ continue
517
+ }
518
+ wg.Add(1)
519
+ go func(maddr ma.Multiaddr) {
520
+ defer wg.Done()
521
+ ctx, cancel := context.WithTimeout(context.Background(), dnsResolveTimeout)
522
+ raddrs, err := madns.Resolve(ctx, maddr)
523
+ cancel()
524
+ if err != nil {
525
+ resolveErrC <- err
526
+ return
527
+ }
528
+ if len(raddrs) == 0 {
529
+ resolveErrC <- fmt.Errorf("non-resolvable multiaddr about %v", maddr)
530
+ return
531
+ }
532
+ // filter out addresses that still doesn't end in `ipfs/Qm...`
533
+ for _, raddr := range raddrs {
534
+ if _, err := raddr.ValueForProtocol(ma.P_IPFS); err != ma.ErrProtocolNotFound {
535
+ maddrs = append(maddrs, raddr)
536
+ }
537
+ }
538
+ }(maddr)
539
+ }
540
+ // wait for address resolving
541
+ wg.Wait()
542
+
543
+ select {
544
+ case err := <-resolveErrC:
545
+ return nil, err
546
+ default:
547
+ }
548
+
549
+ return maddrs, nil
550
+}
551
+
552
var swarmFiltersCmd = &cmds.Command{
553
Helptext: cmdkit.HelpText{
554
Tagline: "Manipulate address filters.",