routeable.go raw

   1  package routeable
   2  
   3  import (
   4  	"errors"
   5  	"net"
   6  	"strings"
   7  	
   8  	"github.com/jackpal/gateway"
   9  )
  10  
  11  // TODO: android and ios need equivalent functions as gateway.DiscoverGateway
  12  
  13  // Gateway stores the current network default gateway as discovered by
  14  // github.com/jackpal/gateway
  15  var Gateway net.IP
  16  
  17  // Address is the network address that routes to the gateway and thus the
  18  // internet
  19  var Address net.IP
  20  
  21  // IPNet is the subnet of the Gateway's LAN
  22  var IPNet *net.IPNet
  23  
  24  // Interface is the net.Interface of the Address above
  25  var Interface *net.Interface
  26  //
  27  // // SecondaryAddresses are all the other addresses that can be reached from
  28  // // somewhere (including localhost) but not necessarily the internet
  29  // var SecondaryAddresses []net.IP
  30  //
  31  // // SecondaryInterfaces is the interfaces of the SecondaryAddresses stored in the
  32  // // corresponding slice index
  33  // var SecondaryInterfaces []*net.Interface
  34  
  35  // GetAddressesAndInterfaces returns all of the addresses and interfaces that
  36  // would be resolved from an automatic addresses that can connect two processes at all
  37  func GetAddressesAndInterfaces() (Interfaces []*net.Interface, Addresses map[string]struct{}) {
  38  	if Address == nil || Interface == nil {
  39  		if Discover() != nil {
  40  			E.Ln("no routeable address found")
  41  		}
  42  	}
  43  	Interfaces = append(Interfaces, Interface)
  44  	// Interfaces = append(Interfaces, SecondaryInterfaces...)
  45  	Addresses = make(map[string]struct{})
  46  	Addresses[Address.String()] = struct{}{}
  47  	// for i := range SecondaryAddresses {
  48  	// 	Addresses[SecondaryAddresses[i].String()] = struct{}{}
  49  	// }
  50  	// D.S(Interfaces)
  51  	// D.S(Addresses)
  52  	return
  53  }
  54  
  55  // Discover enumerates and evaluates all known network interfaces and addresses
  56  // and filters it down to the ones that reach both a LAN and the internet
  57  //
  58  // We are only interested in IPv4 addresses because for the most part, domestic
  59  // ISPs do not issue their customers with IPv6 routing, it's still a pain in the
  60  // ass outside of large data centre connections
  61  func Discover() (e error) {
  62  	D.Ln("discovering routeable interfaces and addresses...")
  63  	var nif []net.Interface
  64  	if nif, e = net.Interfaces(); E.Chk(e) {
  65  		return
  66  	}
  67  	// D.Ln("number of available network interfaces:", len(nif))
  68  	// D.S(nif)
  69  	var secondaryInterfaces []*net.Interface
  70  	var secondaryAddresses []net.IP
  71  	if Gateway, e = gateway.DiscoverGateway(); E.Chk(e) {
  72  		// todo: this error condition always happens on iOS and Android
  73  		// return
  74  		for i := range nif {
  75  			T.Ln(nif[i])
  76  		}
  77  	} else {
  78  		var gw net.IP
  79  		if Gateway != nil {
  80  			gws := Gateway.String()
  81  			gw = net.ParseIP(gws)
  82  		}
  83  		for i := range nif {
  84  			var addrs []net.Addr
  85  			if addrs, e = nif[i].Addrs(); E.Chk(e) || addrs == nil {
  86  				continue
  87  			}
  88  			for j := range addrs {
  89  				var in *net.IPNet
  90  				if _, in, e = net.ParseCIDR(addrs[j].String()); E.Chk(e) {
  91  					continue
  92  				}
  93  				if Gateway != nil && in.Contains(gw) {
  94  					Address = net.ParseIP(strings.Split(addrs[j].String(), "/")[0])
  95  					Interface = &nif[i]
  96  					IPNet = in
  97  					continue
  98  				}
  99  				ip, _, _ := net.ParseCIDR(addrs[j].String())
 100  				if strings.HasPrefix(ip.String(), "169.") || strings.HasPrefix(ip.String(), "fe80:") {
 101  					continue
 102  				}
 103  				if strings.HasPrefix(ip.String(), "127.") || strings.HasPrefix(ip.String(), "::1") {
 104  					continue
 105  				}
 106  				secondaryAddresses = append(secondaryAddresses, ip)
 107  				secondaryInterfaces = append(secondaryInterfaces, &nif[i])
 108  			}
 109  		}
 110  	}
 111  	// SecondaryAddresses = secondaryAddresses
 112  	// SecondaryInterfaces = secondaryInterfaces
 113  	T.Ln("Gateway", Gateway)
 114  	T.Ln("Address", Address)
 115  	T.Ln("Interface", Interface.Name)
 116  	// T.Ln("SecondaryAddresses")
 117  	// for i := range SecondaryInterfaces {
 118  	// 	T.Ln(SecondaryInterfaces[i].Name, SecondaryAddresses[i].String())
 119  	// }
 120  	return
 121  }
 122  
 123  // GetInterface returns the address and interface of multicast-and-internet capable interfaces
 124  func GetInterface() (ifc *net.Interface, address string, e error) {
 125  	if Address == nil || Interface == nil {
 126  		if Discover() != nil {
 127  			e = errors.New("no routeable address found")
 128  			return
 129  		}
 130  	}
 131  	address = Address.String()
 132  	ifc = Interface
 133  	return
 134  }
 135  
 136  func GetListenable() net.IP {
 137  	if Address == nil {
 138  		if Discover() != nil {
 139  			E.Ln("no routeable address found")
 140  		}
 141  	}
 142  	return Address
 143  }
 144  
 145  func GetAllInterfacesAndAddresses() (interfaces []*net.Interface, udpAddrs []*net.UDPAddr) {
 146  	if Discover() != nil {
 147  		E.Ln("no routeable address found")
 148  		return
 149  	}
 150  	interfaces = []*net.Interface{Interface}
 151  	naddrs := []net.IP{Address}
 152  	var addrs []*net.IP
 153  	for i := range naddrs {
 154  		addrs = append(addrs, &naddrs[i])
 155  	}
 156  	var e error
 157  	for i := range addrs {
 158  		var udpAddr *net.UDPAddr
 159  		if udpAddr, e = net.ResolveUDPAddr("udp", addrs[i].String()+":0"); !E.Chk(e) {
 160  			udpAddrs = append(udpAddrs, udpAddr)
 161  		}
 162  	}
 163  	return
 164  }
 165