diff --git a/common/src/main/java/io/netty/util/internal/PlatformDependent.java b/common/src/main/java/io/netty/util/internal/PlatformDependent.java index 91a265b30e1..2322858d8a6 100644 --- a/common/src/main/java/io/netty/util/internal/PlatformDependent.java +++ b/common/src/main/java/io/netty/util/internal/PlatformDependent.java @@ -15,6 +15,7 @@ */ package io.netty.util.internal; +import io.netty.util.CharsetUtil; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import org.jctools.queues.MpscArrayQueue; @@ -28,19 +29,27 @@ import org.jctools.util.Pow2; import org.jctools.util.UnsafeAccess; +import java.io.BufferedReader; import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Collections; import java.util.Deque; +import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Queue; import java.util.Random; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentMap; @@ -97,6 +106,10 @@ public final class PlatformDependent { private static final String NORMALIZED_ARCH = normalizeArch(SystemPropertyUtil.get("os.arch", "")); private static final String NORMALIZED_OS = normalizeOs(SystemPropertyUtil.get("os.name", "")); + // keep in sync with maven builds! + private static final String[] ALLOWED_LINUX_OS_CLASSIFIERS = {"fedora", "suse", "arch"}; + private static final Set LINUX_OS_CLASSIFIERS = new LinkedHashSet(); + private static final int ADDRESS_SIZE = addressSize0(); private static final boolean USE_DIRECT_BUFFER_NO_CLEANER; private static final AtomicLong DIRECT_MEMORY_COUNTER; @@ -196,6 +209,48 @@ public Random current() { "Unless explicitly requested, heap buffer will always be preferred to avoid potential system " + "instability."); } + + // For specifications, see https://www.freedesktop.org/software/systemd/man/os-release.html + final String[] OS_RELEASE_FILES = {"/etc/os-release", "/usr/lib/os-release"}; + final String LINUX_ID_PREFIX = "ID="; + final String LINUX_ID_LIKE_PREFIX = "ID_LIKE="; + final HashSet allowedClassifiers = new HashSet(); + Collections.addAll(allowedClassifiers, ALLOWED_LINUX_OS_CLASSIFIERS); + + for (String osReleaseFileName : OS_RELEASE_FILES) { + final File file = new File(osReleaseFileName); + if (file.exists()) { + BufferedReader reader = null; + try { + reader = new BufferedReader( + new InputStreamReader( + new FileInputStream(file), CharsetUtil.UTF_8)); + + String line; + while ((line = reader.readLine()) != null) { + if (line.startsWith(LINUX_ID_PREFIX)) { + String id = normalizeOsReleaseVariableValue(line.substring(LINUX_ID_PREFIX.length())); + addClassifier(allowedClassifiers, id); + } else if (line.startsWith(LINUX_ID_LIKE_PREFIX)) { + line = normalizeOsReleaseVariableValue(line.substring(LINUX_ID_LIKE_PREFIX.length())); + addClassifier(allowedClassifiers, line.split("[ ]+")); + } + } + } catch (IOException ignored) { + // Ignore + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException ignored) { + // Ignore + } + } + } + // specification states we should only fall back if /etc/os-release does not exist + break; + } + } } public static boolean hasDirectBufferNoCleanerConstructor() { @@ -1274,6 +1329,23 @@ public static String normalizedOs() { return NORMALIZED_OS; } + public static Set normalizedLinuxClassifiers() { + return Collections.unmodifiableSet(LINUX_OS_CLASSIFIERS); + } + + private static void addClassifier(HashSet allowedClassifiers, String... split) { + for (String id : split) { + if (allowedClassifiers.contains(id)) { + LINUX_OS_CLASSIFIERS.add(id); + } + } + } + + private static String normalizeOsReleaseVariableValue(String value) { + // Variable assignment values may be enclosed in double or single quotes. + return value.trim().replaceAll("[\"']", ""); + } + private static String normalize(String value) { return value.toLowerCase(Locale.US).replaceAll("[^a-z0-9]+", ""); } diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java b/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java index 3d404838071..8dbca2b138c 100644 --- a/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java +++ b/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java @@ -552,15 +552,25 @@ private static void loadTcNative() throws Exception { String os = PlatformDependent.normalizedOs(); String arch = PlatformDependent.normalizedArch(); - Set libNames = new LinkedHashSet(4); + Set libNames = new LinkedHashSet(5); String staticLibName = "netty_tcnative"; // First, try loading the platform-specific library. Platform-specific // libraries will be available if using a tcnative uber jar. - libNames.add(staticLibName + "_" + os + '_' + arch); if ("linux".equalsIgnoreCase(os)) { - // Fedora SSL lib so naming (libssl.so.10 vs libssl.so.1.0.0).. + Set classifiers = PlatformDependent.normalizedLinuxClassifiers(); + for (String classifier : classifiers) { + libNames.add(staticLibName + "_" + os + '_' + arch + "_" + classifier); + } + // generic arch-dependent library + libNames.add(staticLibName + "_" + os + '_' + arch); + + // Fedora SSL lib so naming (libssl.so.10 vs libssl.so.1.0.0). + // note: should already be included from the classifiers but if not, we use this as an + // additional fallback option here libNames.add(staticLibName + "_" + os + '_' + arch + "_fedora"); + } else { + libNames.add(staticLibName + "_" + os + '_' + arch); } libNames.add(staticLibName + "_" + arch); libNames.add(staticLibName); diff --git a/pom.xml b/pom.xml index fcd1e39422f..d82943e7c0e 100644 --- a/pom.xml +++ b/pom.xml @@ -296,8 +296,9 @@ -D_ - fedora 1.6.2 + + fedora,suse,arch netty-tcnative 2.0.25.Final ${os.detected.classifier}