github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/net/swarm/addrs.go (about) 1 package swarm 2 3 import ( 4 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net" 5 6 ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" 7 ) 8 9 // ListenAddresses returns a list of addresses at which this swarm listens. 10 func (s *Swarm) ListenAddresses() []ma.Multiaddr { 11 addrs := make([]ma.Multiaddr, len(s.listeners)) 12 for i, l := range s.listeners { 13 addrs[i] = l.Multiaddr() 14 } 15 return addrs 16 } 17 18 // InterfaceListenAddresses returns a list of addresses at which this swarm 19 // listens. It expands "any interface" addresses (/ip4/0.0.0.0, /ip6/::) to 20 // use the known local interfaces. 21 func (s *Swarm) InterfaceListenAddresses() ([]ma.Multiaddr, error) { 22 return resolveUnspecifiedAddresses(s.ListenAddresses()) 23 } 24 25 // resolveUnspecifiedAddresses expands unspecified ip addresses (/ip4/0.0.0.0, /ip6/::) to 26 // use the known local interfaces. 27 func resolveUnspecifiedAddresses(unspecifiedAddrs []ma.Multiaddr) ([]ma.Multiaddr, error) { 28 var outputAddrs []ma.Multiaddr 29 30 // todo optimize: only fetch these if we have a "any" addr. 31 ifaceAddrs, err := interfaceAddresses() 32 if err != nil { 33 return nil, err 34 } 35 36 for _, a := range unspecifiedAddrs { 37 38 // split address into its components 39 split := ma.Split(a) 40 41 // if first component (ip) is not unspecified, use it as is. 42 if !manet.IsIPUnspecified(split[0]) { 43 outputAddrs = append(outputAddrs, a) 44 continue 45 } 46 47 // unspecified? add one address per interface. 48 for _, ia := range ifaceAddrs { 49 split[0] = ia 50 joined := ma.Join(split...) 51 outputAddrs = append(outputAddrs, joined) 52 } 53 } 54 55 log.Info("InterfaceListenAddresses:", outputAddrs) 56 return outputAddrs, nil 57 } 58 59 // interfaceAddresses returns a list of addresses associated with local machine 60 func interfaceAddresses() ([]ma.Multiaddr, error) { 61 maddrs, err := manet.InterfaceMultiaddrs() 62 if err != nil { 63 return nil, err 64 } 65 66 var nonLoopback []ma.Multiaddr 67 for _, a := range maddrs { 68 if !manet.IsIPLoopback(a) { 69 nonLoopback = append(nonLoopback, a) 70 } 71 } 72 73 return nonLoopback, nil 74 } 75 76 // addrInList returns whether or not an address is part of a list. 77 // this is useful to check if NAT is happening (or other bugs?) 78 func addrInList(addr ma.Multiaddr, list []ma.Multiaddr) bool { 79 for _, addr2 := range list { 80 if addr.Equal(addr2) { 81 return true 82 } 83 } 84 return false 85 } 86 87 // checkNATWarning checks if our observed addresses differ. if so, 88 // informs the user that certain things might not work yet 89 func (s *Swarm) checkNATWarning(observed ma.Multiaddr) { 90 listen, err := s.InterfaceListenAddresses() 91 if err != nil { 92 log.Errorf("Error retrieving swarm.InterfaceListenAddresses: %s", err) 93 return 94 } 95 96 if !addrInList(observed, listen) { // probably a nat 97 log.Warningf(natWarning, observed, listen) 98 } 99 } 100 101 const natWarning = `Remote peer observed our address to be: %s 102 The local addresses are: %s 103 Thus, connection is going through NAT, and other connections may fail. 104 105 IPFS NAT traversal is still under development. Please bug us on github or irc to fix this. 106 Baby steps: http://jbenet.static.s3.amazonaws.com/271dfcf/baby-steps.gif 107 `