package games.strategy.net; /** * nekromancer@users.sourceforge.net * Utility class for finding the local ip address of a machine with multiple network interfaces. * This class will discard any InetAddress whose isLoobackAddresS() returns true. * It will also discard any InetAddress whose isLinkLocalAddress() returns true. * On most systems the IP addres it uses for internet communication will NOT be * a LinkLocalAddress. Even if your system goes through a gateway, the standard * 192.168.0.1 address will be valid (not link local and not loopback). It is up * to the user to tell his/her opponents the IP address of his/her gateway to * connect to. And it is their responsibility to make sure they have port forwarding * and IP masquarading set properly. TripleA will be bound to their local address * and all packets will be routed through the gateway. Opponents will be bound to the * gateway address. In essence it should all work. * IF the game is run on the system that is acting as the dedicated gateway, many IPs * will be found as valid. The 1st IP that will be detected will be used. According to * some tests, the 1st ip tends to be the IP used by the gateway to connect to the net. * This means that TripleA will still work. */ import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; public class IPFinder { /** * We iterate through an enumeration of network interfaces on the machine * and picks the first IP that is not a loopback and not a link local and not private. * In the case of IRIX computers connected on a LAN through a central * gateway running java off a telnet session will result in a null * network interface (patched below). * * @exception java.net.SocketException * required by InetAddress * @exception java.net.UnknownHostException * required for getLocalHost() * @return java.net.InetAddress the ip address to use */ public static InetAddress findInetAddress() throws SocketException, UnknownHostException { final Enumeration<NetworkInterface> enum1 = NetworkInterface.getNetworkInterfaces(); // Test if null, no point taking a performance hit by // letting the JVM check for a NullPointerException. if (enum1 == null) { final InetAddress ip1 = InetAddress.getLocalHost(); return ip1; } final List<InetAddress> allButLoopback = new ArrayList<>(); while (enum1.hasMoreElements()) { final NetworkInterface netface = enum1.nextElement(); final Enumeration<InetAddress> enum2 = netface.getInetAddresses(); while (enum2.hasMoreElements()) { final InetAddress ip2 = enum2.nextElement(); if (!ip2.isLoopbackAddress()) { allButLoopback.add(ip2); } } } // try to find one that is not private and ip4 for (final InetAddress address : allButLoopback) { if (address.getAddress().length == 4 && !isPrivateNetworkAddress(address)) { return address; } } // try to find one that is not private for (final InetAddress address : allButLoopback) { if (!isPrivateNetworkAddress(address)) { return address; } } // try to find one that is not link local for (final InetAddress address : allButLoopback) { if (!address.isLinkLocalAddress()) { return address; } } // all else fails, return localhost return InetAddress.getLocalHost(); } // end static findInetAddress() private static boolean isPrivateNetworkAddress(final InetAddress address) { // stupid java signed byte type final byte _192 = (byte) 0xC0; final byte _172 = (byte) 0xAC; final byte _168 = (byte) 0xA8; final byte _169 = (byte) 0xA9; final byte _252 = (byte) 0xFC; final byte _254 = (byte) 0xFE; final byte[] bytes = address.getAddress(); // ip 4 if (bytes.length == 4) { // http://en.wikipedia.org/wiki/Private_network if ((bytes[0] == 10) || (bytes[0] == _172 && bytes[1] >= 16 && bytes[1] <= 31) || (bytes[0] == _192 && bytes[1] == _168) || (bytes[0] == _169 && bytes[1] == _254)) { return true; } } else { // ip 6 // http://en.wikipedia.org/wiki/IPv6#Addressing if ((bytes[0] == _252 && bytes[1] == 0) || bytes[0] == _254) { return true; } } return false; } }