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  `