Browse Source
* In the case of multiple network cards, a valid host is returned * In the case of multiple network cards, a valid host is returned * In the case of multiple network cards, a valid host is returned * In the case of multiple network cards, a valid host is returned * fix LOCAL_ADDRESS not assigned value * fix LOCAL_ADDRESS not assigned value * fix LOCAL_ADDRESS not assigned value * fix lock error * fix lock error * end * end * end * end * code smell * code smell * code smell * code smell * code smell * code smell * code smell * lowering * messy * small change * compile error Co-authored-by: dailidong <dailidong66@gmail.com> Co-authored-by: gabry.wu <gabrywu@apache.org>pull/3/MERGE
CalvinKirs
5 years ago
committed by
GitHub
17 changed files with 309 additions and 68 deletions
@ -0,0 +1,209 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You 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.apache.dolphinscheduler.common.utils; |
||||||
|
|
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.net.*; |
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Optional; |
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
import static java.util.Collections.emptyList; |
||||||
|
|
||||||
|
/** |
||||||
|
* NetUtils |
||||||
|
*/ |
||||||
|
public class NetUtils { |
||||||
|
|
||||||
|
|
||||||
|
private NetUtils() { |
||||||
|
throw new IllegalStateException("Utility class"); |
||||||
|
} |
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(NetUtils.class); |
||||||
|
|
||||||
|
private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); |
||||||
|
|
||||||
|
private static String ANY_HOST_VALUE = "0.0.0.0"; |
||||||
|
|
||||||
|
private static String LOCAL_HOST_VALUE = "127.0.0.1"; |
||||||
|
|
||||||
|
private static InetAddress LOCAL_ADDRESS = null; |
||||||
|
|
||||||
|
private static volatile String HOST_ADDRESS; |
||||||
|
|
||||||
|
public static String getHost() { |
||||||
|
if (HOST_ADDRESS != null) { |
||||||
|
return HOST_ADDRESS; |
||||||
|
} |
||||||
|
|
||||||
|
InetAddress address = getLocalAddress(); |
||||||
|
if (address != null) { |
||||||
|
HOST_ADDRESS = address.getHostAddress(); |
||||||
|
return HOST_ADDRESS; |
||||||
|
} |
||||||
|
return LOCAL_HOST_VALUE; |
||||||
|
} |
||||||
|
|
||||||
|
private static InetAddress getLocalAddress() { |
||||||
|
if (null != LOCAL_ADDRESS) { |
||||||
|
return LOCAL_ADDRESS; |
||||||
|
} |
||||||
|
return getLocalAddress0(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Find first valid IP from local network card |
||||||
|
* |
||||||
|
* @return first valid local IP |
||||||
|
*/ |
||||||
|
private static synchronized InetAddress getLocalAddress0() { |
||||||
|
if (null != LOCAL_ADDRESS) { |
||||||
|
return LOCAL_ADDRESS; |
||||||
|
} |
||||||
|
InetAddress localAddress = null; |
||||||
|
NetworkInterface networkInterface = findNetworkInterface(); |
||||||
|
Enumeration<InetAddress> addresses = networkInterface.getInetAddresses(); |
||||||
|
while (addresses.hasMoreElements()) { |
||||||
|
Optional<InetAddress> addressOp = toValidAddress(addresses.nextElement()); |
||||||
|
if (addressOp.isPresent()) { |
||||||
|
try { |
||||||
|
if (addressOp.get().isReachable(100)) { |
||||||
|
LOCAL_ADDRESS = addressOp.get(); |
||||||
|
return LOCAL_ADDRESS; |
||||||
|
} |
||||||
|
} catch (IOException e) { |
||||||
|
logger.warn("test address id reachable io exception", e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
localAddress = InetAddress.getLocalHost(); |
||||||
|
} catch (UnknownHostException e) { |
||||||
|
logger.warn("InetAddress get LocalHost exception", e); |
||||||
|
} |
||||||
|
Optional<InetAddress> addressOp = toValidAddress(localAddress); |
||||||
|
if (addressOp.isPresent()) { |
||||||
|
LOCAL_ADDRESS = addressOp.get(); |
||||||
|
} |
||||||
|
return LOCAL_ADDRESS; |
||||||
|
} |
||||||
|
|
||||||
|
private static Optional<InetAddress> toValidAddress(InetAddress address) { |
||||||
|
if (address instanceof Inet6Address) { |
||||||
|
Inet6Address v6Address = (Inet6Address) address; |
||||||
|
if (isPreferIPV6Address()) { |
||||||
|
return Optional.ofNullable(normalizeV6Address(v6Address)); |
||||||
|
} |
||||||
|
} |
||||||
|
if (isValidV4Address(address)) { |
||||||
|
return Optional.of(address); |
||||||
|
} |
||||||
|
return Optional.empty(); |
||||||
|
} |
||||||
|
|
||||||
|
private static InetAddress normalizeV6Address(Inet6Address address) { |
||||||
|
String addr = address.getHostAddress(); |
||||||
|
int i = addr.lastIndexOf('%'); |
||||||
|
if (i > 0) { |
||||||
|
try { |
||||||
|
return InetAddress.getByName(addr.substring(0, i) + '%' + address.getScopeId()); |
||||||
|
} catch (UnknownHostException e) { |
||||||
|
logger.debug("Unknown IPV6 address: ", e); |
||||||
|
} |
||||||
|
} |
||||||
|
return address; |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean isValidV4Address(InetAddress address) { |
||||||
|
|
||||||
|
if (address == null || address.isLoopbackAddress()) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
String name = address.getHostAddress(); |
||||||
|
return (name != null |
||||||
|
&& IP_PATTERN.matcher(name).matches() |
||||||
|
&& !ANY_HOST_VALUE.equals(name) |
||||||
|
&& !LOCAL_HOST_VALUE.equals(name)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Check if an ipv6 address |
||||||
|
* |
||||||
|
* @return true if it is reachable |
||||||
|
*/ |
||||||
|
private static boolean isPreferIPV6Address() { |
||||||
|
return Boolean.getBoolean("java.net.preferIPv6Addresses"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the suitable {@link NetworkInterface} |
||||||
|
* |
||||||
|
* @return If no {@link NetworkInterface} is available , return <code>null</code> |
||||||
|
*/ |
||||||
|
private static NetworkInterface findNetworkInterface() { |
||||||
|
|
||||||
|
List<NetworkInterface> validNetworkInterfaces = emptyList(); |
||||||
|
|
||||||
|
try { |
||||||
|
validNetworkInterfaces = getValidNetworkInterfaces(); |
||||||
|
} catch (SocketException e) { |
||||||
|
logger.warn("ValidNetworkInterfaces exception", e); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
return validNetworkInterfaces.get(0); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the valid {@link NetworkInterface network interfaces} |
||||||
|
* |
||||||
|
* @throws SocketException SocketException if an I/O error occurs. |
||||||
|
*/ |
||||||
|
private static List<NetworkInterface> getValidNetworkInterfaces() throws SocketException { |
||||||
|
List<NetworkInterface> validNetworkInterfaces = new LinkedList<>(); |
||||||
|
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); |
||||||
|
while (interfaces.hasMoreElements()) { |
||||||
|
NetworkInterface networkInterface = interfaces.nextElement(); |
||||||
|
if (ignoreNetworkInterface(networkInterface)) { // ignore
|
||||||
|
continue; |
||||||
|
} |
||||||
|
validNetworkInterfaces.add(networkInterface); |
||||||
|
} |
||||||
|
return validNetworkInterfaces; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param networkInterface {@link NetworkInterface} |
||||||
|
* @return if the specified {@link NetworkInterface} should be ignored, return <code>true</code> |
||||||
|
* @throws SocketException SocketException if an I/O error occurs. |
||||||
|
*/ |
||||||
|
public static boolean ignoreNetworkInterface(NetworkInterface networkInterface) throws SocketException { |
||||||
|
return networkInterface == null |
||||||
|
|| networkInterface.isLoopback() |
||||||
|
|| networkInterface.isVirtual() |
||||||
|
|| !networkInterface.isUp(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
/* |
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||||
|
* contributor license agreements. See the NOTICE file distributed with |
||||||
|
* this work for additional information regarding copyright ownership. |
||||||
|
* The ASF licenses this file to You 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.apache.dolphinscheduler.common.utils; |
||||||
|
|
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
import java.net.InetAddress; |
||||||
|
|
||||||
|
import static org.junit.Assert.*; |
||||||
|
import static org.mockito.Mockito.mock; |
||||||
|
import static org.mockito.Mockito.when; |
||||||
|
|
||||||
|
/** |
||||||
|
* NetUtilsTest |
||||||
|
*/ |
||||||
|
public class NetUtilsTest { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testGetLocalHost() { |
||||||
|
assertNotNull(NetUtils.getHost()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testIsValidAddress() { |
||||||
|
assertFalse(NetUtils.isValidV4Address(null)); |
||||||
|
InetAddress address = mock(InetAddress.class); |
||||||
|
when(address.isLoopbackAddress()).thenReturn(true); |
||||||
|
assertFalse(NetUtils.isValidV4Address(address)); |
||||||
|
address = mock(InetAddress.class); |
||||||
|
when(address.getHostAddress()).thenReturn("localhost"); |
||||||
|
assertFalse(NetUtils.isValidV4Address(address)); |
||||||
|
address = mock(InetAddress.class); |
||||||
|
when(address.getHostAddress()).thenReturn("0.0.0.0"); |
||||||
|
assertFalse(NetUtils.isValidV4Address(address)); |
||||||
|
address = mock(InetAddress.class); |
||||||
|
when(address.getHostAddress()).thenReturn("127.0.0.1"); |
||||||
|
assertFalse(NetUtils.isValidV4Address(address)); |
||||||
|
address = mock(InetAddress.class); |
||||||
|
when(address.getHostAddress()).thenReturn("1.2.3.4"); |
||||||
|
assertTrue(NetUtils.isValidV4Address(address)); |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue