/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package org.ros.address; import com.google.common.collect.Lists; import com.google.common.net.InetAddresses; import org.ros.exception.RosRuntimeException; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.UnknownHostException; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; /** * @author damonkohler@google.com (Damon Kohler) */ public class InetAddressFactory { private InetAddressFactory() { // Utility class } private static boolean isIpv4(InetAddress address) { return address.getAddress().length == 4; } private static Collection<InetAddress> getAllInetAddresses() { List<NetworkInterface> networkInterfaces; try { networkInterfaces = Collections.list(NetworkInterface.getNetworkInterfaces()); } catch (SocketException e) { throw new RosRuntimeException(e); } List<InetAddress> inetAddresses = Lists.newArrayList(); for (NetworkInterface networkInterface : networkInterfaces) { try { if (networkInterface.isUp()) { inetAddresses.addAll(Collections.list(networkInterface.getInetAddresses())); } } catch (SocketException e) { throw new RosRuntimeException(e); } } return inetAddresses; } private static InetAddress filterInetAddresses(Collection<InetAddress> inetAddresses) { for (InetAddress address : inetAddresses) { // IPv4 only for now. if (!address.isLoopbackAddress() && isIpv4(address)) { return address; } } throw new RosRuntimeException("No non-loopback interface found."); } public static InetAddress newNonLoopback() { return filterInetAddresses(getAllInetAddresses()); } public static InetAddress newNonLoopbackForNetworkInterface(NetworkInterface networkInterface) { return filterInetAddresses(Collections.list(networkInterface.getInetAddresses())); } private static Collection<InetAddress> getAllInetAddressesByName(String host) { InetAddress[] allAddressesByName; try { allAddressesByName = org.xbill.DNS.Address.getAllByName(host); } catch (UnknownHostException unused) { try { allAddressesByName = InetAddress.getAllByName(host); } catch (UnknownHostException e) { throw new RosRuntimeException(e); } } return Arrays.asList(allAddressesByName); } /** * Creates an {@link InetAddress} with both an IP and a host set so that no * further resolving will take place. * * If an IP address string is specified, this method ensures that it will be * used in place of a host name. * * If a host name other than {@code Address.LOCALHOST} is specified, this * method trys to find a non-loopback IP associated with the supplied host * name. * * If the specified host name is {@code Address.LOCALHOST}, this method * returns a loopback address. * * @param host * @return an {@link InetAddress} with both an IP and a host set (no further * resolving will take place) */ public static InetAddress newFromHostString(String host) { try { if (InetAddresses.isInetAddress(host)) { return InetAddress.getByAddress(host, InetAddresses.forString(host).getAddress()); } if (host.equals(Address.LOCALHOST)) { return InetAddress.getByAddress(Address.LOCALHOST, InetAddresses.forString(Address.LOOPBACK).getAddress()); } } catch (UnknownHostException e) { throw new RosRuntimeException(e); } Collection<InetAddress> allAddressesByName = getAllInetAddressesByName(host); // First, try to find a non-loopback IPv4 address. for (InetAddress address : allAddressesByName) { if (!address.isLoopbackAddress() && isIpv4(address)) { return address; } } // Return a loopback IPv4 address as a last resort. for (InetAddress address : allAddressesByName) { if (isIpv4(address)) { return address; } } throw new RosRuntimeException("Unable to construct InetAddress for host: " + host); } public static InetAddress newLoopback() { return newFromHostString(Address.LOOPBACK); } }