diff --git a/src/com/barchart/udt/SocketUDT.java b/src/com/barchart/udt/SocketUDT.java index 9ccec37a..1195533f 100644 --- a/src/com/barchart/udt/SocketUDT.java +++ b/src/com/barchart/udt/SocketUDT.java @@ -10,6 +10,7 @@ package com.barchart.udt; import com.barchart.udt.anno.Native; import com.barchart.udt.nio.KindUDT; import com.barchart.udt.util.HelpUDT; +import dorkbox.network.util.NativeLoader; import dorkbox.util.FileUtil; import dorkbox.util.OS; import dorkbox.util.OsType; @@ -17,30 +18,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.math.BigInteger; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.URI; import java.net.URL; -import java.net.URLDecoder; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.security.CodeSource; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.security.ProtectionDomain; -import java.util.Arrays; -import java.util.Enumeration; import java.util.List; -import java.util.Locale; import java.util.Set; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; /** * UDT native socket wrapper @@ -159,87 +146,32 @@ class SocketUDT { if (isContainer) { // have to extract our correct file to temp then load it, ONLY if we are not already loaded! + String sourceFileName = "udt-core-2.3.2"; + if (OS.isLinux()) { + sourceFileName += ".so"; + } + else if (OS.isWindows()) { + sourceFileName += ".dll"; + } + else { + sourceFileName += ".dylib"; + } + try { - MessageDigest digest = MessageDigest.getInstance("MD5"); - digest.update(TypeUDT.class.getName() - .getBytes()); - - // convert to alpha-numeric. see https://stackoverflow.com/questions/29183818/why-use-tostring32-and-not-tostring36 - final String outputFileName = "UDT_driver_" + new BigInteger(1, digest.digest()).toString(32) - .toUpperCase(Locale.US); - - final String tempDir = System.getProperty("java.io.tmpdir"); - - final File file = new File(tempDir, outputFileName); - if (!file.canRead()) { - // we need to iterate this jar to get the files - - final String packageName = TypeUDT.class.getPackage() - .getName() - .replaceAll("\\.", "/"); - - final String prefix = packageName + "/natives/" + osName + "/"; - final List list = Arrays.asList(os.getLibraryNames()); - - final String jarFileName = URLDecoder.decode(loc.getPath(), "UTF-8"); - JarFile jar = new JarFile(jarFileName); - Enumeration entries = jar.entries(); - JAR_READ: - while (entries.hasMoreElements()) { - final JarEntry jarEntry = entries.nextElement(); - String name = jarEntry.getName(); - - if (name.startsWith(prefix)) { - for (String s : list) { - if (name.endsWith(s)) { - // there is only one! - - // now we copy it out - final InputStream inputStream = jar.getInputStream(jarEntry); - - OutputStream outStream = null; - try { - outStream = new FileOutputStream(file); - - byte[] buffer = new byte[2048]; - int read; - while ((read = inputStream.read(buffer)) > 0) { - outStream.write(buffer, 0, read); - } - } catch (IOException e) { - log.error("Error extracting library from: " + jarFileName, e.getMessage()); - } finally { - try { - inputStream.close(); - } catch (Exception ignored) { - } - try { - if (outStream != null) { - outStream.close(); - } - } catch (Exception ignored) { - } - } - break JAR_READ; - } - } - } - } - - jar.close(); - } - log.info("Loading release libraries."); - System.load(file.getAbsolutePath()); + final String packageName = TypeUDT.class.getPackage() + .getName() + .replaceAll("\\.", "/"); + + sourceFileName = packageName + "/natives/" + osName + "/" + sourceFileName; + + NativeLoader.loadLibrary(sourceFileName, "networkUDT_", TypeUDT.class); + log.info("Release libraries loaded."); loaded = true; - } catch (NoSuchAlgorithmException e) { - log.error("Error loading MD5 checksum.", e.getMessage()); - } catch (UnsupportedEncodingException e) { - log.error("Error parsing text.", e.getMessage()); - } catch (IOException e) { - log.error("Error extracting library.", e.getMessage()); + } catch (Exception e) { + log.error(e.getMessage()); } } else { diff --git a/src/com/barchart/udt/natives/linux_32/libbarchart-udt-core-2.3.2.so b/src/com/barchart/udt/natives/linux_32/udt-core-2.3.2.so similarity index 100% rename from src/com/barchart/udt/natives/linux_32/libbarchart-udt-core-2.3.2.so rename to src/com/barchart/udt/natives/linux_32/udt-core-2.3.2.so diff --git a/src/com/barchart/udt/natives/linux_64/libbarchart-udt-core-2.3.2.so b/src/com/barchart/udt/natives/linux_64/udt-core-2.3.2.so similarity index 100% rename from src/com/barchart/udt/natives/linux_64/libbarchart-udt-core-2.3.2.so rename to src/com/barchart/udt/natives/linux_64/udt-core-2.3.2.so diff --git a/src/com/barchart/udt/natives/macosx_32/libbarchart-udt-core-2.3.2.dylib b/src/com/barchart/udt/natives/macosx_32/udt-core-2.3.2.dylib similarity index 100% rename from src/com/barchart/udt/natives/macosx_32/libbarchart-udt-core-2.3.2.dylib rename to src/com/barchart/udt/natives/macosx_32/udt-core-2.3.2.dylib diff --git a/src/com/barchart/udt/natives/macosx_64/libbarchart-udt-core-2.3.2.dylib b/src/com/barchart/udt/natives/macosx_64/udt-core-2.3.2.dylib similarity index 100% rename from src/com/barchart/udt/natives/macosx_64/libbarchart-udt-core-2.3.2.dylib rename to src/com/barchart/udt/natives/macosx_64/udt-core-2.3.2.dylib diff --git a/src/com/barchart/udt/natives/windows_32/libbarchart-udt-core-2.3.2.dll b/src/com/barchart/udt/natives/windows_32/udt-core-2.3.2.dll similarity index 100% rename from src/com/barchart/udt/natives/windows_32/libbarchart-udt-core-2.3.2.dll rename to src/com/barchart/udt/natives/windows_32/udt-core-2.3.2.dll diff --git a/src/com/barchart/udt/natives/windows_64/libbarchart-udt-core-2.3.2.dll b/src/com/barchart/udt/natives/windows_64/udt-core-2.3.2.dll similarity index 100% rename from src/com/barchart/udt/natives/windows_64/libbarchart-udt-core-2.3.2.dll rename to src/com/barchart/udt/natives/windows_64/udt-core-2.3.2.dll diff --git a/src/dorkbox/network/util/NativeLinuxEpoll.java b/src/dorkbox/network/util/NativeLinuxEpoll.java new file mode 100644 index 00000000..8169898d --- /dev/null +++ b/src/dorkbox/network/util/NativeLinuxEpoll.java @@ -0,0 +1,162 @@ +/* + * Copyright 2016 dorkbox, llc + * + * Licensed 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 dorkbox.network.util; + +/** + * The contents of this method are used to rewrite (via javassist, via the BuildDependencyJars build) the NativeLibraryLoader.load method. + * + * This is necessary so that we don't continuously recreate the native library every time we start. + * + * Also, this file is not included in the build process. + */ +public +class NativeLinuxEpoll { + + public static + void load(String name, ClassLoader loader) { +// try { +// String var0 = $1; +// ClassLoader var1 = $2; +// if (var0.equals("netty-transport-native-epoll")) { +// String sourceFileName = "META-INF/native/lib" + var0 + ".so"; +// String suffix = ".so"; +// +// String version = dorkbox.network.Server.getVersion(); +// +// final String outputFileName = "lib" + var0 + "." + version + suffix; +// final String tempDir = System.getProperty("java.io.tmpdir"); +// +// final java.io.File file = new java.io.File(tempDir, outputFileName); +// if (!file.canRead()) { +// java.net.URL url = var1.getResource(sourceFileName); +// +// System.err.println("Loading: " + file.getAbsolutePath()); +// +// // now we copy it out +// final java.io.InputStream inputStream = url.openStream(); +// +// java.io.OutputStream outStream = null; +// try { +// outStream = new java.io.FileOutputStream(file); +// +// byte[] buffer = new byte[4096]; +// int read; +// while ((read = inputStream.read(buffer)) > 0) { +// outStream.write(buffer, 0, read); +// } +// +// outStream.flush(); +// outStream.close(); +// outStream = null; +// } finally { +// try { +// inputStream.close(); +// } catch (Exception ignored) { +// } +// try { +// if (outStream != null) { +// outStream.close(); +// } +// } catch (Exception ignored) { +// } +// } +// } +// +// System.load(file.getAbsolutePath()); +// } +// else { +// // default file operation +// +// String libname = System.mapLibraryName(var0); +// String path = io.netty.util.internal.NativeLibraryLoader.NATIVE_RESOURCE_HOME + libname; +// +// java.net.URL url = var1.getResource(path); +// if (url == null && io.netty.util.internal.NativeLibraryLoader.isOSX()) { +// if (path.endsWith(".jnilib")) { +// url = var1.getResource(io.netty.util.internal.NativeLibraryLoader.NATIVE_RESOURCE_HOME + "lib" + var0 + ".dynlib"); +// } +// else { +// url = var1.getResource(io.netty.util.internal.NativeLibraryLoader.NATIVE_RESOURCE_HOME + "lib" + var0 + ".jnilib"); +// } +// } +// +// if (url == null) { +// // Fall back to normal loading of JNI stuff +// System.loadLibrary(var0); +// return; +// } +// +// int index = libname.lastIndexOf('.'); +// String prefix = libname.substring(0, index); +// String suffix = libname.substring(index, libname.length()); +// java.io.InputStream in = null; +// java.io.OutputStream out = null; +// java.io.File tmpFile = null; +// boolean loaded = false; +// try { +// tmpFile = java.io.File.createTempFile(prefix, suffix, io.netty.util.internal.NativeLibraryLoader.WORKDIR); +// in = url.openStream(); +// out = new java.io.FileOutputStream(tmpFile); +// +// byte[] buffer = new byte[8192]; +// int length; +// while ((length = in.read(buffer)) > 0) { +// out.write(buffer, 0, length); +// } +// out.flush(); +// out.close(); +// out = null; +// +// System.load(tmpFile.getPath()); +// loaded = true; +// } catch (Exception e) { +// throw (UnsatisfiedLinkError) new UnsatisfiedLinkError("could not load a native library: " + var0).initCause(e); +// } finally { +// if (in != null) { +// try { +// in.close(); +// } catch (java.io.IOException ignore) { +// // ignore +// } +// } +// if (out != null) { +// try { +// out.close(); +// } catch (java.io.IOException ignore) { +// // ignore +// } +// } +// if (tmpFile != null) { +// if (loaded) { +// tmpFile.deleteOnExit(); +// } +// else { +// if (!tmpFile.delete()) { +// tmpFile.deleteOnExit(); +// } +// } +// } +// } +// } +// } catch (Exception e) { +// e.printStackTrace(); +// } + } + + private + NativeLinuxEpoll() { + } +} diff --git a/src/dorkbox/network/util/NativeLoader.java b/src/dorkbox/network/util/NativeLoader.java new file mode 100644 index 00000000..d0523b3c --- /dev/null +++ b/src/dorkbox/network/util/NativeLoader.java @@ -0,0 +1,96 @@ +/* + * Copyright 2016 dorkbox, llc + * + * Licensed 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 dorkbox.network.util; + +import dorkbox.network.Server; +import dorkbox.util.OS; +import io.netty.util.internal.PlatformDependent; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.rmi.server.ExportException; + +/** + * Loads the specified library, extracting it from the jar, if necessary + */ +public +class NativeLoader { + + public static + void loadLibrary(final String sourceFileName, final String destinationPrefix, final Class classLoaderClass) throws Exception { + try { + String suffix; + if (OS.isLinux()) { + suffix = ".so"; + } + else if (OS.isWindows()) { + suffix = ".dll"; + } + else { + suffix = ".dylib"; + } + + final String outputFileName = destinationPrefix + "." + Server.getVersion() + suffix; + final String tempDir = System.getProperty("java.io.tmpdir"); + + final File file = new File(tempDir, outputFileName); + if (!file.canRead()) { + ClassLoader loader = PlatformDependent.getClassLoader(classLoaderClass); + URL url = loader.getResource(sourceFileName); + + // now we copy it out + final InputStream inputStream = url.openStream(); + + OutputStream outStream = null; + try { + outStream = new FileOutputStream(file); + + byte[] buffer = new byte[4096]; + int read; + while ((read = inputStream.read(buffer)) > 0) { + outStream.write(buffer, 0, read); + } + + outStream.flush(); + outStream.close(); + outStream = null; + } finally { + try { + inputStream.close(); + } catch (Exception ignored) { + } + try { + if (outStream != null) { + outStream.close(); + } + } catch (Exception ignored) { + } + } + } + + System.load(file.getAbsolutePath()); + } catch (Exception e) { + throw new ExportException("Error extracting library: " + sourceFileName, e); + } + } + + private + NativeLoader() { + } +}