diff --git a/native/src/main/c/NativeCompressImpl.c b/native/src/main/c/NativeCompressImpl.c index 7fb8e6b9..b6b27682 100644 --- a/native/src/main/c/NativeCompressImpl.c +++ b/native/src/main/c/NativeCompressImpl.c @@ -3,6 +3,7 @@ #include #include "shared.h" +#include "cpuid_helper.h" #include "net_md_5_bungee_jni_zlib_NativeCompressImpl.h" typedef unsigned char byte; @@ -26,6 +27,10 @@ jint throwException(JNIEnv *env, const char* message, int err) { return (*env)->Throw(env, throwable); } +JNIEXPORT jboolean JNICALL Java_net_md_15_bungee_jni_zlib_NativeCompressImpl_checkSupported(JNIEnv* env, jobject obj) { + return (jboolean) checkCompressionNativesSupport(); +} + void JNICALL Java_net_md_15_bungee_jni_zlib_NativeCompressImpl_reset(JNIEnv* env, jobject obj, jlong ctx, jboolean compress) { z_stream* stream = (z_stream*) ctx; int ret = (compress) ? deflateReset(stream) : inflateReset(stream); diff --git a/native/src/main/c/cpuid_helper.h b/native/src/main/c/cpuid_helper.h new file mode 100644 index 00000000..2394ecd6 --- /dev/null +++ b/native/src/main/c/cpuid_helper.h @@ -0,0 +1,22 @@ +// Header to check for SSE 4.2 support in compression natives +// GCC only! + +#ifndef _INCLUDE_CPUID_HELPER_H +#define _INCLUDE_CPUID_HELPER_H + +#include +#include + +static inline bool checkCompressionNativesSupport() { + unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; + if(__get_cpuid(1, &eax, &ebx, &ecx, &edx)) { + return (ecx & bit_PCLMUL) != 0 && (ecx & bit_SSE4_2) != 0; + }else { + return false; + } +} + +#endif // _INCLUDE_CPUID_HELPER_H diff --git a/native/src/main/c/net_md_5_bungee_jni_zlib_NativeCompressImpl.h b/native/src/main/c/net_md_5_bungee_jni_zlib_NativeCompressImpl.h index befb7dcc..5c73e131 100644 --- a/native/src/main/c/net_md_5_bungee_jni_zlib_NativeCompressImpl.h +++ b/native/src/main/c/net_md_5_bungee_jni_zlib_NativeCompressImpl.h @@ -15,6 +15,14 @@ extern "C" { JNIEXPORT void JNICALL Java_net_md_15_bungee_jni_zlib_NativeCompressImpl_initFields (JNIEnv *, jclass); +/* + * Class: net_md_5_bungee_jni_zlib_NativeCompressImpl + * Method: checkSupported + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_net_md_15_bungee_jni_zlib_NativeCompressImpl_checkSupported + (JNIEnv *, jobject); + /* * Class: net_md_5_bungee_jni_zlib_NativeCompressImpl * Method: end diff --git a/native/src/main/java/net/md_5/bungee/jni/NativeCode.java b/native/src/main/java/net/md_5/bungee/jni/NativeCode.java index 62bdaa0e..be4d5b0b 100644 --- a/native/src/main/java/net/md_5/bungee/jni/NativeCode.java +++ b/native/src/main/java/net/md_5/bungee/jni/NativeCode.java @@ -15,14 +15,23 @@ public final class NativeCode private final String name; private final Supplier javaImpl; private final Supplier nativeImpl; + private final boolean enableNativeFlag; + private final boolean extendedSupportCheck; // private boolean loaded; public NativeCode(String name, Supplier javaImpl, Supplier nativeImpl) + { + this( name, javaImpl, nativeImpl, false ); + } + + public NativeCode(String name, Supplier javaImpl, Supplier nativeImpl, boolean extendedSupportCheck) { this.name = name; this.javaImpl = javaImpl; this.nativeImpl = nativeImpl; + this.enableNativeFlag = Boolean.parseBoolean( System.getProperty( "net.md_5.bungee.jni." + name + ".enable", "true" ) ); + this.extendedSupportCheck = extendedSupportCheck; } public T newInstance() @@ -32,7 +41,7 @@ public final class NativeCode public boolean load() { - if ( !loaded && isSupported() ) + if ( enableNativeFlag && !loaded && isSupported() ) { String fullName = "bungeecord-" + name; @@ -59,6 +68,13 @@ public final class NativeCode } System.load( temp.getPath() ); + + if ( extendedSupportCheck ) + { + // Should throw NativeCodeException if incompatible + nativeImpl.get(); + } + loaded = true; } catch ( IOException ex ) { @@ -66,6 +82,9 @@ public final class NativeCode } catch ( UnsatisfiedLinkError ex ) { System.out.println( "Could not load native library: " + ex.getMessage() ); + } catch ( NativeCodeException ex ) + { + System.out.println( "Native library " + name + " is incompatible: " + ex.getMessage() ); } } } diff --git a/native/src/main/java/net/md_5/bungee/jni/NativeCodeException.java b/native/src/main/java/net/md_5/bungee/jni/NativeCodeException.java index 1ac8f590..d264675c 100644 --- a/native/src/main/java/net/md_5/bungee/jni/NativeCodeException.java +++ b/native/src/main/java/net/md_5/bungee/jni/NativeCodeException.java @@ -7,4 +7,10 @@ public class NativeCodeException extends RuntimeException { super( message + " : " + reason ); } + + public NativeCodeException(String message) + { + super( message ); + } + } diff --git a/native/src/main/java/net/md_5/bungee/jni/zlib/NativeCompressImpl.java b/native/src/main/java/net/md_5/bungee/jni/zlib/NativeCompressImpl.java index f78caf18..d91f9b58 100644 --- a/native/src/main/java/net/md_5/bungee/jni/zlib/NativeCompressImpl.java +++ b/native/src/main/java/net/md_5/bungee/jni/zlib/NativeCompressImpl.java @@ -15,6 +15,8 @@ public class NativeCompressImpl static native void initFields(); + native boolean checkSupported(); + native void end(long ctx, boolean compress); native void reset(long ctx, boolean compress); diff --git a/native/src/main/java/net/md_5/bungee/jni/zlib/NativeZlib.java b/native/src/main/java/net/md_5/bungee/jni/zlib/NativeZlib.java index e9fe82b8..96e30777 100644 --- a/native/src/main/java/net/md_5/bungee/jni/zlib/NativeZlib.java +++ b/native/src/main/java/net/md_5/bungee/jni/zlib/NativeZlib.java @@ -15,6 +15,14 @@ public class NativeZlib implements BungeeZlib private boolean compress; private long ctx; + public NativeZlib() + { + if ( !nativeCompress.checkSupported() ) + { + throw new NativeCodeException( "This CPU does not support the required SSE 4.2 and/or PCLMUL extensions!" ); + } + } + @Override public void init(boolean compress, int level) { diff --git a/native/src/main/resources/native-compress.so b/native/src/main/resources/native-compress.so index 2ebbfed6..181396f1 100755 Binary files a/native/src/main/resources/native-compress.so and b/native/src/main/resources/native-compress.so differ diff --git a/native/src/test/java/net/md_5/bungee/NativeZlibTest.java b/native/src/test/java/net/md_5/bungee/NativeZlibTest.java index 70b2b475..112a3b83 100644 --- a/native/src/test/java/net/md_5/bungee/NativeZlibTest.java +++ b/native/src/test/java/net/md_5/bungee/NativeZlibTest.java @@ -15,7 +15,7 @@ import org.junit.jupiter.api.Test; public class NativeZlibTest { - private final NativeCode factory = new NativeCode<>( "native-compress", JavaZlib::new, NativeZlib::new ); + private final NativeCode factory = new NativeCode<>( "native-compress", JavaZlib::new, NativeZlib::new, true ); @Test public void doTest() throws DataFormatException diff --git a/proxy/src/main/java/net/md_5/bungee/compress/CompressFactory.java b/proxy/src/main/java/net/md_5/bungee/compress/CompressFactory.java index 2e0c63d1..e4cbbeb7 100644 --- a/proxy/src/main/java/net/md_5/bungee/compress/CompressFactory.java +++ b/proxy/src/main/java/net/md_5/bungee/compress/CompressFactory.java @@ -8,5 +8,5 @@ import net.md_5.bungee.jni.zlib.NativeZlib; public class CompressFactory { - public static final NativeCode zlib = new NativeCode<>( "native-compress", JavaZlib::new, NativeZlib::new ); + public static final NativeCode zlib = new NativeCode<>( "native-compress", JavaZlib::new, NativeZlib::new, true ); }