001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.reef.wake.remote.address; 020 021import org.apache.reef.tang.Configuration; 022import org.apache.reef.tang.Tang; 023import org.apache.reef.wake.exception.WakeRuntimeException; 024 025import javax.inject.Inject; 026import java.net.Inet4Address; 027import java.net.InetAddress; 028import java.net.NetworkInterface; 029import java.net.SocketException; 030import java.util.Comparator; 031import java.util.Enumeration; 032import java.util.TreeSet; 033import java.util.concurrent.atomic.AtomicReference; 034import java.util.logging.Level; 035import java.util.logging.Logger; 036 037/** 038 * An implementation of LocalAddressProvider using the (removed) code from NetUtils.getLocalAddress(). 039 * @deprecated in 0.14. Use HostnameBasedLocalAddressProvider instead 040 */ 041@Deprecated 042public final class LegacyLocalAddressProvider implements LocalAddressProvider { 043 private static final Logger LOG = Logger.getLogger(LegacyLocalAddressProvider.class.getName()); 044 private final AtomicReference<String> cached = new AtomicReference<>(); 045 046 /** 047 * Injectable constructor for Tang only. 048 */ 049 @Inject 050 private LegacyLocalAddressProvider() { 051 LOG.log(Level.FINE, "Instantiating LegacyLocalAddressProvider"); 052 } 053 054 @Override 055 public String getLocalAddress() { 056 // This method is surprisingly slow: It was causing unit test timeouts, so we memoize the result. 057 if (cached.get() == null) { 058 final Enumeration<NetworkInterface> ifaces; 059 try { 060 ifaces = NetworkInterface.getNetworkInterfaces(); 061 final TreeSet<Inet4Address> sortedAddrs = new TreeSet<>(new AddressComparator()); 062 // There is an idea of virtual / subinterfaces exposed by java here. 063 // We're not walking around looking for those because the javadoc says: 064 065 // "NOTE: can use getNetworkInterfaces()+getInetAddresses() to obtain all IP addresses for this node" 066 067 while (ifaces.hasMoreElements()) { 068 final NetworkInterface iface = ifaces.nextElement(); 069// if(iface.isUp()) { // leads to slowness and non-deterministic return values, so don't call isUp(). 070 final Enumeration<InetAddress> addrs = iface.getInetAddresses(); 071 while (addrs.hasMoreElements()) { 072 final InetAddress a = addrs.nextElement(); 073 if (a instanceof Inet4Address) { 074 sortedAddrs.add((Inet4Address) a); 075 } 076// } 077 } 078 } 079 if (sortedAddrs.isEmpty()) { 080 throw new WakeRuntimeException("This machine apparently doesn't have any IP addresses (not even 127.0.0.1) " + 081 "on interfaces that are up."); 082 } 083 cached.set(sortedAddrs.pollFirst().getHostAddress()); 084 LOG.log(Level.FINE, "Local address is {0}", cached.get()); 085 } catch (final SocketException e) { 086 throw new WakeRuntimeException("Unable to get local host address", e); 087 } 088 } 089 return cached.get(); 090 } 091 092 @Override 093 public Configuration getConfiguration() { 094 return Tang.Factory.getTang().newConfigurationBuilder() 095 .bind(LocalAddressProvider.class, LegacyLocalAddressProvider.class) 096 .build(); 097 } 098 099 private static class AddressComparator implements Comparator<Inet4Address> { 100 101 // get unsigned byte. 102 private static int u(final byte b) { 103 return (int) b; // & 0xff; 104 } 105 106 @Override 107 public int compare(final Inet4Address aa, final Inet4Address ba) { 108 final byte[] a = aa.getAddress(); 109 final byte[] b = ba.getAddress(); 110 // local subnet comes after all else. 111 if (a[0] == 127 && b[0] != 127) { 112 return 1; 113 } 114 if (a[0] != 127 && b[0] == 127) { 115 return -1; 116 } 117 for (int i = 0; i < 4; i++) { 118 if (u(a[i]) < u(b[i])) { 119 return -1; 120 } 121 if (u(a[i]) > u(b[i])) { 122 return 1; 123 } 124 } 125 return 0; 126 } 127 } 128}