func pickLocalAddr(laddrs []ma.Multiaddr, raddr ma.Multiaddr) (laddr ma.Multiaddr) { if len(laddrs) < 1 { return nil } // make sure that we ONLY use local addrs that match the remote addr. laddrs = manet.AddrMatch(raddr, laddrs) if len(laddrs) < 1 { return nil } // make sure that we ONLY use local addrs that CAN dial the remote addr. // filter out all the local addrs that aren't capable raddrIPLayer := ma.Split(raddr)[0] raddrIsLoopback := manet.IsIPLoopback(raddrIPLayer) raddrIsLinkLocal := manet.IsIP6LinkLocal(raddrIPLayer) laddrs = addrutil.FilterAddrs(laddrs, func(a ma.Multiaddr) bool { laddrIPLayer := ma.Split(a)[0] laddrIsLoopback := manet.IsIPLoopback(laddrIPLayer) laddrIsLinkLocal := manet.IsIP6LinkLocal(laddrIPLayer) if laddrIsLoopback { // our loopback addrs can only dial loopbacks. return raddrIsLoopback } if laddrIsLinkLocal { return raddrIsLinkLocal // out linklocal addrs can only dial link locals. } return true }) // TODO pick with a good heuristic // we use a random one for now to prevent bad addresses from making nodes unreachable // with a random selection, multiple tries may work. return laddrs[rand.Intn(len(laddrs))] }
// Builds and returns the Multiaddrs for the swarm to listen on func BuildSwarmAddrs(port int) [][]byte { // Get all interface addresses all, _ := manet.InterfaceMultiaddrs() // Filter out loopback and link-local addresses var filtered []ma.Multiaddr for _, m := range all { if manet.IsIPLoopback(m) { continue } if manet.IsIP6LinkLocal(m) { continue } filtered = append(filtered, m) } // Add tcp/<port> to each address and convert to byte representation prt, err := ma.NewMultiaddr(fmt.Sprintf("/tcp/%d", port)) if err != nil { panic(err) } var listenAddrs [][]byte for _, a := range filtered { listenAddrs = append(listenAddrs, a.Encapsulate(prt).Bytes()) } return listenAddrs }
// AddrOverNonLocalIP returns whether the addr uses a non-local ip link func AddrOverNonLocalIP(a ma.Multiaddr) bool { split := ma.Split(a) if len(split) < 1 { return false } if manet.IsIP6LinkLocal(split[0]) { return false } return true }
// AddrIsShareableOnWAN returns whether the given address should be shareable on the // wide area network (wide internet). func AddrIsShareableOnWAN(addr ma.Multiaddr) bool { s := ma.Split(addr) if len(s) < 1 { return false } a := s[0] if manet.IsIPLoopback(a) || manet.IsIP6LinkLocal(a) || manet.IsIPUnspecified(a) { return false } return manet.IsThinWaist(a) }
func TestInterfaceAddrs(t *testing.T) { addrs, err := InterfaceAddresses() if err != nil { t.Fatal(err) } if len(addrs) < 1 { t.Error("no addresses") } for _, a := range addrs { if manet.IsIP6LinkLocal(a) { t.Error("should not return ip link local addresses", a) } } if len(addrs) < 1 { t.Error("no good interface addrs") } }