add waiting for network interfaces to network utils

This commit is contained in:
Jörg Prante 2020-10-20 20:10:40 +02:00
parent 453fc20615
commit 7ce935df64
10 changed files with 115 additions and 72 deletions

View file

@ -3,6 +3,11 @@ plugins {
id "io.codearte.nexus-staging" version "0.21.1" id "io.codearte.nexus-staging" version "0.21.1"
} }
wrapper {
gradleVersion = "${rootProject.property('gradle.wrapper.version')}"
distributionType = Wrapper.DistributionType.ALL
}
ext { ext {
user = 'jprante' user = 'jprante'
name = 'netty-http' name = 'netty-http'

View file

@ -2,7 +2,7 @@ group = org.xbib
name = netty-http name = netty-http
version = 4.1.52.1 version = 4.1.52.1
gradle.wrapper.version = 6.4.1 gradle.wrapper.version = 6.6.1
netty.version = 4.1.52.Final netty.version = 4.1.52.Final
tcnative.version = 2.0.34.Final tcnative.version = 2.0.34.Final
bouncycastle.version = 1.66 bouncycastle.version = 1.66

Binary file not shown.

View file

@ -1,6 +1,5 @@
#Wed May 20 11:53:57 CEST 2020
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-all.zip
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

2
gradlew vendored
View file

@ -130,7 +130,7 @@ fi
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"` APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"` JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath # We build the pattern for arguments to be converted via cygpath

21
gradlew.bat vendored
View file

@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init if "%ERRORLEVEL%" == "0" goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -54,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=% set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init if exist "%JAVA_EXE%" goto execute
echo. echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@ -64,21 +64,6 @@ echo location of your Java installation.
goto fail goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute :execute
@rem Setup the command line @rem Setup the command line
@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell

View file

@ -19,6 +19,11 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -28,8 +33,6 @@ import java.util.logging.Logger;
*/ */
public class NetworkUtils { public class NetworkUtils {
private static final Logger logger = Logger.getLogger(NetworkUtils.class.getName());
private static final String lf = System.lineSeparator(); private static final String lf = System.lineSeparator();
private static final char[] hexDigit = new char[]{ private static final char[] hexDigit = new char[]{
@ -40,14 +43,22 @@ public class NetworkUtils {
private static final String IPV6_SETTING = "java.net.preferIPv6Addresses"; private static final String IPV6_SETTING = "java.net.preferIPv6Addresses";
private static final CountDownLatch latch = new CountDownLatch(1);
private static final InterfaceWaiter interfaceWaiter = new InterfaceWaiter();
private static InetAddress localAddress; private static InetAddress localAddress;
private NetworkUtils() {
throw new UnsupportedOperationException();
}
public static void extendSystemProperties() { public static void extendSystemProperties() {
InetAddress address; InetAddress address;
try { try {
address = InetAddress.getLocalHost(); address = InetAddress.getLocalHost();
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.WARNING, e.getMessage(), e); Logger.getLogger("network").log(Level.WARNING, e.getMessage(), e);
address = InetAddress.getLoopbackAddress(); address = InetAddress.getLoopbackAddress();
} }
localAddress = address; localAddress = address;
@ -67,18 +78,14 @@ public class NetworkUtils {
map.put("net." + networkInterface.getDisplayName(), inetAddress.getCanonicalHostName()); map.put("net." + networkInterface.getDisplayName(), inetAddress.getCanonicalHostName());
} }
} }
logger.log(Level.FINE, "found network properties for system properties: " + map);
for (Map.Entry<String, String> entry : map.entrySet()) { for (Map.Entry<String, String> entry : map.entrySet()) {
System.setProperty(entry.getKey(), entry.getValue()); System.setProperty(entry.getKey(), entry.getValue());
} }
} catch (Throwable e) { } catch (Throwable e) {
logger.log(Level.WARNING, e.getMessage(), e); Logger.getLogger("network").log(Level.WARNING, e.getMessage(), e);
} }
} }
private NetworkUtils() {
}
public static boolean isPreferIPv4() { public static boolean isPreferIPv4() {
return Boolean.getBoolean(System.getProperty(IPV4_SETTING)); return Boolean.getBoolean(System.getProperty(IPV4_SETTING));
} }
@ -205,7 +212,15 @@ public class NetworkUtils {
return false; return false;
} }
public static InetAddress getFirstNonLoopbackAddress(NetworkProtocolVersion ipversion) { public static List<NetworkInterface> getAllNetworkInterfaces() throws InterruptedException {
return getInterfaces(n -> true);
}
public static List<NetworkInterface> getAllRunningAndUpInterfaces() throws InterruptedException {
return getInterfaces(NetworkUtils::isUp);
}
public static InetAddress getFirstNonLoopbackAddress(NetworkProtocolVersion ipversion) throws InterruptedException {
InetAddress address; InetAddress address;
for (NetworkInterface networkInterface : getAllNetworkInterfaces()) { for (NetworkInterface networkInterface : getAllNetworkInterfaces()) {
try { try {
@ -213,7 +228,7 @@ public class NetworkUtils {
continue; continue;
} }
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.WARNING, e.getMessage(), e); Logger.getLogger("network").log(Level.WARNING, e.getMessage(), e);
continue; continue;
} }
address = getFirstNonLoopbackAddress(networkInterface, ipversion); address = getFirstNonLoopbackAddress(networkInterface, ipversion);
@ -268,7 +283,7 @@ public class NetworkUtils {
return supportsVersion; return supportsVersion;
} }
public static NetworkProtocolVersion getProtocolVersion() { public static NetworkProtocolVersion getProtocolVersion() throws InterruptedException {
switch (findAvailableProtocols()) { switch (findAvailableProtocols()) {
case IPV4: case IPV4:
return NetworkProtocolVersion.IPV4; return NetworkProtocolVersion.IPV4;
@ -288,7 +303,7 @@ public class NetworkUtils {
return NetworkProtocolVersion.NONE; return NetworkProtocolVersion.NONE;
} }
public static NetworkProtocolVersion findAvailableProtocols() { public static NetworkProtocolVersion findAvailableProtocols() throws InterruptedException {
boolean hasIPv4 = false; boolean hasIPv4 = false;
boolean hasIPv6 = false; boolean hasIPv6 = false;
for (InetAddress addr : getAllAvailableAddresses()) { for (InetAddress addr : getAllAvailableAddresses()) {
@ -311,7 +326,7 @@ public class NetworkUtils {
return NetworkProtocolVersion.NONE; return NetworkProtocolVersion.NONE;
} }
public static InetAddress resolveInetAddress(String hostname, String defaultValue) throws IOException { public static InetAddress resolveInetAddress(String hostname, String defaultValue) throws IOException, InterruptedException {
String host = hostname; String host = hostname;
if (host == null) { if (host == null) {
host = defaultValue; host = defaultValue;
@ -335,14 +350,15 @@ public class NetworkUtils {
} }
} else { } else {
NetworkProtocolVersion networkProtocolVersion = getProtocolVersion(); NetworkProtocolVersion networkProtocolVersion = getProtocolVersion();
String reducedHost = host.substring(0, host.length() - 5);
if (host.toLowerCase(Locale.ROOT).endsWith(":ipv4")) { if (host.toLowerCase(Locale.ROOT).endsWith(":ipv4")) {
networkProtocolVersion = NetworkProtocolVersion.IPV4; networkProtocolVersion = NetworkProtocolVersion.IPV4;
host = host.substring(0, host.length() - 5); host = reducedHost;
} else if (host.toLowerCase(Locale.ROOT).endsWith(":ipv6")) { } else if (host.toLowerCase(Locale.ROOT).endsWith(":ipv6")) {
networkProtocolVersion = NetworkProtocolVersion.IPV6; networkProtocolVersion = NetworkProtocolVersion.IPV6;
host = host.substring(0, host.length() - 5); host = reducedHost;
} }
for (NetworkInterface ni : getInterfaces(NetworkUtils::isUp)) { for (NetworkInterface ni : getAllRunningAndUpInterfaces()) {
if (host.equals(ni.getName()) || host.equals(ni.getDisplayName())) { if (host.equals(ni.getName()) || host.equals(ni.getDisplayName())) {
if (ni.isLoopback()) { if (ni.isLoopback()) {
return getFirstAddress(ni, networkProtocolVersion); return getFirstAddress(ni, networkProtocolVersion);
@ -357,7 +373,7 @@ public class NetworkUtils {
return InetAddress.getByName(host); return InetAddress.getByName(host);
} }
public static InetAddress resolvePublicHostAddress(String host) throws IOException { public static InetAddress resolvePublicHostAddress(String host) throws IOException, InterruptedException {
InetAddress address = resolveInetAddress(host, null); InetAddress address = resolveInetAddress(host, null);
if (address == null || address.isAnyLocalAddress()) { if (address == null || address.isAnyLocalAddress()) {
address = getFirstNonLoopbackAddress(NetworkProtocolVersion.IPV4); address = getFirstNonLoopbackAddress(NetworkProtocolVersion.IPV4);
@ -374,24 +390,9 @@ public class NetworkUtils {
return address; return address;
} }
private static List<NetworkInterface> getAllNetworkInterfaces() { public static List<NetworkInterface> getInterfaces(Predicate<NetworkInterface> predicate) throws InterruptedException {
return getInterfaces(n -> true);
}
public static List<NetworkInterface> getAllRunningAndUpInterfaces() {
return getInterfaces(NetworkUtils::isUp);
}
public static List<NetworkInterface> getInterfaces(Predicate<NetworkInterface> predicate) {
List<NetworkInterface> networkInterfaces = new ArrayList<>(); List<NetworkInterface> networkInterfaces = new ArrayList<>();
Enumeration<NetworkInterface> interfaces; for (NetworkInterface networkInterface : waitForNetworkInterfaces()) {
try {
interfaces = NetworkInterface.getNetworkInterfaces();
} catch (Exception e) {
return networkInterfaces;
}
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
if (predicate.test(networkInterface)) { if (predicate.test(networkInterface)) {
networkInterfaces.add(networkInterface); networkInterfaces.add(networkInterface);
Enumeration<NetworkInterface> subInterfaces = networkInterface.getSubInterfaces(); Enumeration<NetworkInterface> subInterfaces = networkInterface.getSubInterfaces();
@ -404,7 +405,7 @@ public class NetworkUtils {
return networkInterfaces; return networkInterfaces;
} }
public static List<InetAddress> getAllAvailableAddresses() { public static List<InetAddress> getAllAvailableAddresses() throws InterruptedException {
List<InetAddress> allAddresses = new ArrayList<>(); List<InetAddress> allAddresses = new ArrayList<>();
for (NetworkInterface networkInterface : getAllNetworkInterfaces()) { for (NetworkInterface networkInterface : getAllNetworkInterfaces()) {
Enumeration<InetAddress> addrs = networkInterface.getInetAddresses(); Enumeration<InetAddress> addrs = networkInterface.getInetAddresses();
@ -416,15 +417,61 @@ public class NetworkUtils {
return allAddresses; return allAddresses;
} }
public static String displayNetworkInterfaces() { public static List<NetworkInterface> waitForNetworkInterfaces() throws InterruptedException {
return waitForNetworkInterfaces(5L, TimeUnit.SECONDS);
}
public static List<NetworkInterface> waitForNetworkInterfaces(long period, TimeUnit timeUnit) throws InterruptedException {
if (latch.getCount() == 0L) {
return interfaceWaiter.interfaces;
}
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> future = service.scheduleAtFixedRate(interfaceWaiter, 0L, period, timeUnit);
latch.await();
future.cancel(true);
service.shutdownNow();
return interfaceWaiter.interfaces;
}
private static class InterfaceWaiter implements Runnable {
private final List<NetworkInterface> interfaces = new ArrayList<>();
private final Logger logger = Logger.getLogger("network");
@Override
public void run() {
try {
interfaces.clear();
logger.log(Level.INFO, "waiting for network interfaces");
Enumeration<NetworkInterface> networkInterfaceEnumeration = NetworkInterface.getNetworkInterfaces();
if (networkInterfaceEnumeration.hasMoreElements()) {
do {
NetworkInterface networkInterface = networkInterfaceEnumeration.nextElement();
logger.log(Level.INFO, "found " + networkInterface.getDisplayName());
interfaces.add(networkInterface);
} while (networkInterfaceEnumeration.hasMoreElements());
logger.log(Level.INFO, "got network interfaces: " + interfaces.size());
if (!interfaces.isEmpty()) {
latch.countDown();
}
}
} catch (Exception e) {
// getNetworkInterfaces() throws socket exception if no network is configured
logger.log(Level.WARNING, e.getMessage());
}
}
}
public static String getNetworkInterfacesAsString() throws InterruptedException {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (NetworkInterface nic : getAllNetworkInterfaces()) { for (NetworkInterface nic : getAllNetworkInterfaces()) {
sb.append(displayNetworkInterface(nic)); sb.append(getNetworkInterfaceAsString(nic));
} }
return sb.toString(); return sb.toString();
} }
public static String displayNetworkInterface(NetworkInterface nic) { public static String getNetworkInterfaceAsString(NetworkInterface nic) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(lf).append(nic.getName()).append(lf); sb.append(lf).append(nic.getName()).append(lf);
if (!nic.getName().equals(nic.getDisplayName())) { if (!nic.getName().equals(nic.getDisplayName())) {
@ -449,13 +496,13 @@ public class NetworkUtils {
flags.add("VIRTUAL"); flags.add("VIRTUAL");
} }
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.WARNING, e.getMessage(), e); Logger.getLogger("network").log(Level.WARNING, e.getMessage(), e);
} }
sb.append(String.join(",", flags)); sb.append(String.join(",", flags));
try { try {
sb.append(" mtu ").append(nic.getMTU()).append(lf); sb.append(" mtu ").append(nic.getMTU()).append(lf);
} catch (SocketException e) { } catch (SocketException e) {
logger.log(Level.WARNING, e.getMessage(), e); Logger.getLogger("network").log(Level.WARNING, e.getMessage(), e);
} }
List<InterfaceAddress> addresses = nic.getInterfaceAddresses(); List<InterfaceAddress> addresses = nic.getInterfaceAddresses();
for (InterfaceAddress address : addresses) { for (InterfaceAddress address : addresses) {
@ -474,7 +521,7 @@ public class NetworkUtils {
sb.append(lf); sb.append(lf);
} }
} catch (SocketException e) { } catch (SocketException e) {
logger.log(Level.WARNING, e.getMessage(), e); Logger.getLogger("network").log(Level.WARNING, e.getMessage(), e);
} }
return sb.toString(); return sb.toString();
} }
@ -505,7 +552,7 @@ public class NetworkUtils {
try { try {
sb.append(" netmask:").append(format(InetAddress.getByAddress(b))); sb.append(" netmask:").append(format(InetAddress.getByAddress(b)));
} catch (UnknownHostException e) { } catch (UnknownHostException e) {
logger.log(Level.WARNING, e.getMessage(), e); Logger.getLogger("network").log(Level.WARNING, e.getMessage(), e);
} }
InetAddress broadcast = interfaceAddress.getBroadcast(); InetAddress broadcast = interfaceAddress.getBroadcast();
if (broadcast != null) { if (broadcast != null) {

View file

@ -2,10 +2,8 @@ package org.xbib.netty.http.common.test;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.xbib.netty.http.common.HttpParameters; import org.xbib.netty.http.common.HttpParameters;
import java.nio.charset.MalformedInputException; import java.nio.charset.MalformedInputException;
import java.nio.charset.UnmappableCharacterException; import java.nio.charset.UnmappableCharacterException;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
class HttpParametersTest { class HttpParametersTest {

View file

@ -0,0 +1,14 @@
package org.xbib.netty.http.common.test;
import org.junit.jupiter.api.Test;
import org.xbib.netty.http.common.NetworkUtils;
import java.util.logging.Level;
import java.util.logging.Logger;
class NetworkUtilsTest {
@Test
void testInterfaces() throws InterruptedException {
Logger.getLogger("test").log(Level.INFO, NetworkUtils.getNetworkInterfacesAsString());
}
}

View file

@ -17,7 +17,6 @@ import io.netty.util.DomainWildcardMappingBuilder;
import io.netty.util.Mapping; import io.netty.util.Mapping;
import org.xbib.net.URL; import org.xbib.net.URL;
import org.xbib.netty.http.common.HttpAddress; import org.xbib.netty.http.common.HttpAddress;
import org.xbib.netty.http.common.NetworkUtils;
import org.xbib.netty.http.common.HttpChannelInitializer; import org.xbib.netty.http.common.HttpChannelInitializer;
import org.xbib.netty.http.common.TransportProvider; import org.xbib.netty.http.common.TransportProvider;
import org.xbib.netty.http.server.api.Domain; import org.xbib.netty.http.server.api.Domain;
@ -57,10 +56,6 @@ public final class Server implements AutoCloseable {
private static final Logger logger = Logger.getLogger(Server.class.getName()); private static final Logger logger = Logger.getLogger(Server.class.getName());
static { static {
// extend Java system properties by detected network interfaces
if (System.getProperty("xbib.netty.http.client.extendsystemproperties") != null) {
NetworkUtils.extendSystemProperties();
}
// change Netty defaults to safer ones, but still allow override from arg line // change Netty defaults to safer ones, but still allow override from arg line
if (System.getProperty("io.netty.noUnsafe") == null) { if (System.getProperty("io.netty.noUnsafe") == null) {
System.setProperty("io.netty.noUnsafe", Boolean.toString(true)); System.setProperty("io.netty.noUnsafe", Boolean.toString(true));