@@ -3,12 +3,14 @@ package basichost
3
3
import (
4
4
"context"
5
5
"io"
6
+ "net"
6
7
"time"
7
8
8
9
logging "github.com/ipfs/go-log"
9
10
goprocess "github.com/jbenet/goprocess"
10
11
goprocessctx "github.com/jbenet/goprocess/context"
11
12
ifconnmgr "github.com/libp2p/go-libp2p-interface-connmgr"
13
+ inat "github.com/libp2p/go-libp2p-nat"
12
14
inet "github.com/libp2p/go-libp2p-net"
13
15
peer "github.com/libp2p/go-libp2p-peer"
14
16
pstore "github.com/libp2p/go-libp2p-peerstore"
@@ -17,6 +19,7 @@ import (
17
19
ping "github.com/libp2p/go-libp2p/p2p/protocol/ping"
18
20
ma "github.com/multiformats/go-multiaddr"
19
21
madns "github.com/multiformats/go-multiaddr-dns"
22
+ manet "github.com/multiformats/go-multiaddr-net"
20
23
msmux "github.com/multiformats/go-multistream"
21
24
)
22
25
@@ -485,17 +488,15 @@ func (h *BasicHost) Addrs() []ma.Multiaddr {
485
488
}
486
489
487
490
// mergeAddrs merges input address lists, leave only unique addresses
488
- func mergeAddrs ( addrLists ... []ma.Multiaddr ) (uniqueAddrs []ma.Multiaddr ) {
491
+ func dedupAddrs ( addrs []ma.Multiaddr ) (uniqueAddrs []ma.Multiaddr ) {
489
492
exists := make (map [string ]bool )
490
- for _ , addrList := range addrLists {
491
- for _ , addr := range addrList {
492
- k := string (addr .Bytes ())
493
- if exists [k ] {
494
- continue
495
- }
496
- exists [k ] = true
497
- uniqueAddrs = append (uniqueAddrs , addr )
493
+ for _ , addr := range addrs {
494
+ k := string (addr .Bytes ())
495
+ if exists [k ] {
496
+ continue
498
497
}
498
+ exists [k ] = true
499
+ uniqueAddrs = append (uniqueAddrs , addr )
499
500
}
500
501
return uniqueAddrs
501
502
}
@@ -507,19 +508,140 @@ func (h *BasicHost) AllAddrs() []ma.Multiaddr {
507
508
if err != nil {
508
509
log .Debug ("error retrieving network interface addrs" )
509
510
}
510
- var observedAddrs []ma.Multiaddr
511
- if h .ids != nil {
512
- // peer observed addresses
513
- observedAddrs = h .ids .OwnObservedAddrs ()
514
- }
515
- var natAddrs []ma.Multiaddr
511
+ var natMappings []inat.Mapping
512
+
516
513
// natmgr is nil if we do not use nat option;
517
514
// h.natmgr.NAT() is nil if not ready, or no nat is available.
518
515
if h .natmgr != nil && h .natmgr .NAT () != nil {
519
- natAddrs = h .natmgr .NAT ().ExternalAddrs ()
516
+ natMappings = h .natmgr .NAT ().Mappings ()
520
517
}
521
518
522
- return mergeAddrs (listenAddrs , observedAddrs , natAddrs )
519
+ finalAddrs := listenAddrs
520
+ if len (natMappings ) > 0 {
521
+
522
+ // We have successfully mapped ports on our NAT. Use those
523
+ // instead of observed addresses (mostly).
524
+
525
+ // First, generate a mapping table.
526
+ // protocol -> internal port -> external addr
527
+ ports := make (map [string ]map [int ]net.Addr )
528
+ for _ , m := range natMappings {
529
+ addr , err := m .ExternalAddr ()
530
+ if err != nil {
531
+ // mapping not ready yet.
532
+ continue
533
+ }
534
+ protoPorts , ok := ports [m .Protocol ()]
535
+ if ! ok {
536
+ protoPorts = make (map [int ]net.Addr )
537
+ ports [m .Protocol ()] = protoPorts
538
+ }
539
+ protoPorts [m .InternalPort ()] = addr
540
+ }
541
+
542
+ // Next, apply this mapping to our addresses.
543
+ for _ , listen := range listenAddrs {
544
+ found := false
545
+ transport , rest := ma .SplitFunc (listen , func (c ma.Component ) bool {
546
+ if found {
547
+ return true
548
+ }
549
+ switch c .Protocol ().Code {
550
+ case ma .P_TCP , ma .P_UDP :
551
+ found = true
552
+ }
553
+ return false
554
+ })
555
+ if ! manet .IsThinWaist (transport ) {
556
+ continue
557
+ }
558
+
559
+ naddr , err := manet .ToNetAddr (transport )
560
+ if err != nil {
561
+ log .Error ("error parsing net multiaddr %q: %s" , transport , err )
562
+ continue
563
+ }
564
+
565
+ var (
566
+ ip net.IP
567
+ iport int
568
+ protocol string
569
+ )
570
+ switch naddr := naddr .(type ) {
571
+ case * net.TCPAddr :
572
+ ip = naddr .IP
573
+ iport = naddr .Port
574
+ protocol = "tcp"
575
+ case * net.UDPAddr :
576
+ ip = naddr .IP
577
+ iport = naddr .Port
578
+ protocol = "udp"
579
+ default :
580
+ continue
581
+ }
582
+
583
+ if ! ip .IsGlobalUnicast () {
584
+ // We only map global unicast ports.
585
+ continue
586
+ }
587
+
588
+ mappedAddr , ok := ports [protocol ][iport ]
589
+ if ! ok {
590
+ // Not mapped.
591
+ continue
592
+ }
593
+
594
+ mappedMaddr , err := manet .FromNetAddr (mappedAddr )
595
+ if err != nil {
596
+ log .Errorf ("mapped addr can't be turned into a multiaddr %q: %s" , mappedAddr , err )
597
+ continue
598
+ }
599
+
600
+ // Did the router give us a routable public addr?
601
+ if manet .IsPublicAddr (mappedMaddr ) {
602
+ // Yes, use it.
603
+ extMaddr := mappedMaddr
604
+ if rest != nil {
605
+ extMaddr = ma .Join (extMaddr , rest )
606
+ }
607
+
608
+ // Add in the mapped addr.
609
+ finalAddrs = append (finalAddrs , extMaddr )
610
+ continue
611
+ }
612
+
613
+ // No. Ok, let's try our observed addresses.
614
+
615
+ // Now, check if we have any observed addresses that
616
+ // differ from the one reported by the router. Routers
617
+ // don't always give the most accurate information.
618
+ observed := h .ids .ObservedAddrsFor (listen )
619
+
620
+ if len (observed ) == 0 {
621
+ continue
622
+ }
623
+
624
+ // Drop the IP from the external maddr
625
+ _ , extMaddrNoIP := ma .SplitFirst (mappedMaddr )
626
+
627
+ for _ , obsMaddr := range observed {
628
+ // Extract a public observed addr.
629
+ ip , _ := ma .SplitFirst (obsMaddr )
630
+ if ip == nil || ! manet .IsPublicAddr (ip ) {
631
+ continue
632
+ }
633
+
634
+ finalAddrs = append (finalAddrs , ma .Join (ip , extMaddrNoIP ))
635
+ }
636
+ }
637
+ } else {
638
+ var observedAddrs []ma.Multiaddr
639
+ if h .ids != nil {
640
+ observedAddrs = h .ids .OwnObservedAddrs ()
641
+ }
642
+ finalAddrs = append (finalAddrs , observedAddrs ... )
643
+ }
644
+ return dedupAddrs (finalAddrs )
523
645
}
524
646
525
647
// Close shuts down the Host's services (network, etc).
0 commit comments