Fixed Native library issues where it couldn't be loaded and would crash
This commit is contained in:
parent
3d6f4d81f8
commit
bf681688d0
@ -15,12 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.network;
|
package dorkbox.network;
|
||||||
|
|
||||||
import java.net.Inet6Address;
|
import java.net.*;
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.InterfaceAddress;
|
|
||||||
import java.net.NetworkInterface;
|
|
||||||
import java.net.SocketException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
@ -31,15 +26,19 @@ import org.slf4j.Logger;
|
|||||||
|
|
||||||
import dorkbox.network.pipeline.discovery.ClientDiscoverHostHandler;
|
import dorkbox.network.pipeline.discovery.ClientDiscoverHostHandler;
|
||||||
import dorkbox.network.pipeline.discovery.ClientDiscoverHostInitializer;
|
import dorkbox.network.pipeline.discovery.ClientDiscoverHostInitializer;
|
||||||
|
import dorkbox.util.OS;
|
||||||
import io.netty.bootstrap.Bootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelOption;
|
import io.netty.channel.ChannelOption;
|
||||||
|
import io.netty.channel.EventLoopGroup;
|
||||||
import io.netty.channel.nio.NioEventLoopGroup;
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
|
import io.netty.channel.oio.OioEventLoopGroup;
|
||||||
import io.netty.channel.socket.DatagramPacket;
|
import io.netty.channel.socket.DatagramPacket;
|
||||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||||
|
import io.netty.channel.socket.oio.OioDatagramChannel;
|
||||||
|
|
||||||
@SuppressWarnings({"unused", "AutoBoxing"})
|
@SuppressWarnings({"unused", "AutoBoxing"})
|
||||||
public final
|
public final
|
||||||
@ -154,9 +153,21 @@ class Broadcast {
|
|||||||
logger2.info("Searching for host on {} : {}", address, udpPort);
|
logger2.info("Searching for host on {} : {}", address, udpPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
NioEventLoopGroup group = new NioEventLoopGroup();
|
EventLoopGroup group;
|
||||||
|
Class<? extends Channel> channelClass;
|
||||||
|
|
||||||
|
if (OS.isAndroid()) {
|
||||||
|
// android ONLY supports OIO (not NIO)
|
||||||
|
group = new OioEventLoopGroup(1);
|
||||||
|
channelClass = OioDatagramChannel.class;
|
||||||
|
} else {
|
||||||
|
group = new NioEventLoopGroup(1);
|
||||||
|
channelClass = NioDatagramChannel.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Bootstrap udpBootstrap = new Bootstrap().group(group)
|
Bootstrap udpBootstrap = new Bootstrap().group(group)
|
||||||
.channel(NioDatagramChannel.class)
|
.channel(channelClass)
|
||||||
.option(ChannelOption.SO_BROADCAST, true)
|
.option(ChannelOption.SO_BROADCAST, true)
|
||||||
.handler(new ClientDiscoverHostInitializer())
|
.handler(new ClientDiscoverHostInitializer())
|
||||||
.localAddress(new InetSocketAddress(address,
|
.localAddress(new InetSocketAddress(address,
|
||||||
|
@ -53,7 +53,6 @@ import io.netty.channel.socket.nio.NioDatagramChannel;
|
|||||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
import io.netty.channel.socket.oio.OioDatagramChannel;
|
import io.netty.channel.socket.oio.OioDatagramChannel;
|
||||||
import io.netty.channel.socket.oio.OioSocketChannel;
|
import io.netty.channel.socket.oio.OioSocketChannel;
|
||||||
import io.netty.util.internal.PlatformDependent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The client is both SYNC and ASYNC. It starts off SYNC (blocks thread until it's done), then once it's connected to the server, it's
|
* The client is both SYNC and ASYNC. It starts off SYNC (blocks thread until it's done), then once it's connected to the server, it's
|
||||||
@ -113,22 +112,19 @@ class Client<C extends Connection> extends EndPointClient implements Connection
|
|||||||
localChannelName = config.localChannelName;
|
localChannelName = config.localChannelName;
|
||||||
hostName = config.host;
|
hostName = config.host;
|
||||||
|
|
||||||
boolean isAndroid = PlatformDependent.isAndroid();
|
|
||||||
|
|
||||||
|
|
||||||
final EventLoopGroup boss;
|
final EventLoopGroup boss;
|
||||||
|
|
||||||
if (isAndroid) {
|
if (OS.isAndroid()) {
|
||||||
// android ONLY supports OIO (not NIO)
|
// android ONLY supports OIO (not NIO)
|
||||||
boss = new OioEventLoopGroup(0, new NamedThreadFactory(threadName, threadGroup));
|
boss = new OioEventLoopGroup(DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
||||||
}
|
}
|
||||||
else if (OS.isLinux()) {
|
else if (OS.isLinux() && NativeLibrary.isAvailable()) {
|
||||||
// JNI network stack is MUCH faster (but only on linux)
|
// JNI network stack is MUCH faster (but only on linux)
|
||||||
boss = new EpollEventLoopGroup(DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
boss = new EpollEventLoopGroup(DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
||||||
}
|
}
|
||||||
else if (OS.isMacOsX()) {
|
else if (OS.isMacOsX() && NativeLibrary.isAvailable()) {
|
||||||
// KQueue network stack is MUCH faster (but only on macosx)
|
// KQueue network stack is MUCH faster (but only on macosx)
|
||||||
boss = new KQueueEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
boss = new KQueueEventLoopGroup(DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
boss = new NioEventLoopGroup(DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
boss = new NioEventLoopGroup(DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
||||||
@ -164,16 +160,16 @@ class Client<C extends Connection> extends EndPointClient implements Connection
|
|||||||
Bootstrap tcpBootstrap = new Bootstrap();
|
Bootstrap tcpBootstrap = new Bootstrap();
|
||||||
bootstraps.add(new BootstrapWrapper("TCP", config.host, config.tcpPort, tcpBootstrap));
|
bootstraps.add(new BootstrapWrapper("TCP", config.host, config.tcpPort, tcpBootstrap));
|
||||||
|
|
||||||
if (isAndroid) {
|
if (OS.isAndroid()) {
|
||||||
// android ONLY supports OIO (not NIO)
|
// android ONLY supports OIO (not NIO)
|
||||||
tcpBootstrap.channel(OioSocketChannel.class);
|
tcpBootstrap.channel(OioSocketChannel.class);
|
||||||
}
|
}
|
||||||
else if (OS.isLinux()) {
|
else if (OS.isLinux() && NativeLibrary.isAvailable()) {
|
||||||
// JNI network stack is MUCH faster (but only on linux)
|
// JNI network stack is MUCH faster (but only on linux)
|
||||||
tcpBootstrap.channel(EpollSocketChannel.class);
|
tcpBootstrap.channel(EpollSocketChannel.class);
|
||||||
}
|
}
|
||||||
else if (OS.isMacOsX()) {
|
else if (OS.isMacOsX() && NativeLibrary.isAvailable()) {
|
||||||
// JNI network stack is MUCH faster (but only on macosx)
|
// KQueue network stack is MUCH faster (but only on macosx)
|
||||||
tcpBootstrap.channel(KQueueSocketChannel.class);
|
tcpBootstrap.channel(KQueueSocketChannel.class);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -189,7 +185,7 @@ class Client<C extends Connection> extends EndPointClient implements Connection
|
|||||||
serializationManager));
|
serializationManager));
|
||||||
|
|
||||||
// android screws up on this!!
|
// android screws up on this!!
|
||||||
tcpBootstrap.option(ChannelOption.TCP_NODELAY, !isAndroid)
|
tcpBootstrap.option(ChannelOption.TCP_NODELAY, !OS.isAndroid())
|
||||||
.option(ChannelOption.SO_KEEPALIVE, true);
|
.option(ChannelOption.SO_KEEPALIVE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,20 +194,19 @@ class Client<C extends Connection> extends EndPointClient implements Connection
|
|||||||
Bootstrap udpBootstrap = new Bootstrap();
|
Bootstrap udpBootstrap = new Bootstrap();
|
||||||
bootstraps.add(new BootstrapWrapper("UDP", config.host, config.udpPort, udpBootstrap));
|
bootstraps.add(new BootstrapWrapper("UDP", config.host, config.udpPort, udpBootstrap));
|
||||||
|
|
||||||
if (isAndroid) {
|
if (OS.isAndroid()) {
|
||||||
// android ONLY supports OIO (not NIO)
|
// android ONLY supports OIO (not NIO)
|
||||||
udpBootstrap.channel(OioDatagramChannel.class);
|
udpBootstrap.channel(OioDatagramChannel.class);
|
||||||
}
|
}
|
||||||
else if (OS.isLinux()) {
|
else if (OS.isLinux() && NativeLibrary.isAvailable()) {
|
||||||
// JNI network stack is MUCH faster (but only on linux)
|
// JNI network stack is MUCH faster (but only on linux)
|
||||||
udpBootstrap.channel(EpollDatagramChannel.class);
|
udpBootstrap.channel(EpollDatagramChannel.class);
|
||||||
}
|
}
|
||||||
else if (OS.isMacOsX()) {
|
else if (OS.isMacOsX() && NativeLibrary.isAvailable()) {
|
||||||
// JNI network stack is MUCH faster (but only on macosx)
|
// KQueue network stack is MUCH faster (but only on macosx)
|
||||||
udpBootstrap.channel(KQueueDatagramChannel.class);
|
udpBootstrap.channel(KQueueDatagramChannel.class);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// windows
|
|
||||||
udpBootstrap.channel(NioDatagramChannel.class);
|
udpBootstrap.channel(NioDatagramChannel.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +50,8 @@ import io.netty.channel.EventLoopGroup;
|
|||||||
import io.netty.channel.ReflectiveChannelFactory;
|
import io.netty.channel.ReflectiveChannelFactory;
|
||||||
import io.netty.channel.epoll.EpollDatagramChannel;
|
import io.netty.channel.epoll.EpollDatagramChannel;
|
||||||
import io.netty.channel.epoll.EpollEventLoopGroup;
|
import io.netty.channel.epoll.EpollEventLoopGroup;
|
||||||
|
import io.netty.channel.kqueue.KQueueDatagramChannel;
|
||||||
|
import io.netty.channel.kqueue.KQueueEventLoopGroup;
|
||||||
import io.netty.channel.nio.NioEventLoopGroup;
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
import io.netty.channel.oio.OioEventLoopGroup;
|
import io.netty.channel.oio.OioEventLoopGroup;
|
||||||
import io.netty.channel.socket.DatagramChannel;
|
import io.netty.channel.socket.DatagramChannel;
|
||||||
@ -59,7 +61,6 @@ import io.netty.channel.socket.oio.OioDatagramChannel;
|
|||||||
import io.netty.resolver.HostsFileEntriesResolver;
|
import io.netty.resolver.HostsFileEntriesResolver;
|
||||||
import io.netty.resolver.ResolvedAddressTypes;
|
import io.netty.resolver.ResolvedAddressTypes;
|
||||||
import io.netty.util.concurrent.Future;
|
import io.netty.util.concurrent.Future;
|
||||||
import io.netty.util.internal.PlatformDependent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A DnsClient for resolving DNS name, with reasonably good defaults.
|
* A DnsClient for resolving DNS name, with reasonably good defaults.
|
||||||
@ -232,16 +233,21 @@ class DnsClient extends Shutdownable {
|
|||||||
DnsClient(Collection<InetSocketAddress> nameServerAddresses) {
|
DnsClient(Collection<InetSocketAddress> nameServerAddresses) {
|
||||||
super(DnsClient.class);
|
super(DnsClient.class);
|
||||||
|
|
||||||
if (PlatformDependent.isAndroid()) {
|
if (OS.isAndroid()) {
|
||||||
// android ONLY supports OIO (not NIO)
|
// android ONLY supports OIO (not NIO)
|
||||||
eventLoopGroup = new OioEventLoopGroup(1, new NamedThreadFactory(THREAD_NAME + "-DNS", threadGroup));
|
eventLoopGroup = new OioEventLoopGroup(1, new NamedThreadFactory(THREAD_NAME + "-DNS", threadGroup));
|
||||||
channelType = OioDatagramChannel.class;
|
channelType = OioDatagramChannel.class;
|
||||||
}
|
}
|
||||||
else if (OS.isLinux()) {
|
else if (OS.isLinux() && NativeLibrary.isAvailable()) {
|
||||||
// JNI network stack is MUCH faster (but only on linux)
|
// JNI network stack is MUCH faster (but only on linux)
|
||||||
eventLoopGroup = new EpollEventLoopGroup(1, new NamedThreadFactory(THREAD_NAME + "-DNS", threadGroup));
|
eventLoopGroup = new EpollEventLoopGroup(1, new NamedThreadFactory(THREAD_NAME + "-DNS", threadGroup));
|
||||||
channelType = EpollDatagramChannel.class;
|
channelType = EpollDatagramChannel.class;
|
||||||
}
|
}
|
||||||
|
else if (OS.isMacOsX() && NativeLibrary.isAvailable()) {
|
||||||
|
// KQueue network stack is MUCH faster (but only on macosx)
|
||||||
|
eventLoopGroup = new KQueueEventLoopGroup(1, new NamedThreadFactory(THREAD_NAME + "-DNS", threadGroup));
|
||||||
|
channelType = KQueueDatagramChannel.class;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
eventLoopGroup = new NioEventLoopGroup(1, new NamedThreadFactory(THREAD_NAME + "-DNS", threadGroup));
|
eventLoopGroup = new NioEventLoopGroup(1, new NamedThreadFactory(THREAD_NAME + "-DNS", threadGroup));
|
||||||
channelType = NioDatagramChannel.class;
|
channelType = NioDatagramChannel.class;
|
||||||
|
@ -30,7 +30,6 @@ import io.netty.channel.ChannelFuture;
|
|||||||
import io.netty.channel.ChannelOption;
|
import io.netty.channel.ChannelOption;
|
||||||
import io.netty.channel.EventLoopGroup;
|
import io.netty.channel.EventLoopGroup;
|
||||||
import io.netty.channel.WriteBufferWaterMark;
|
import io.netty.channel.WriteBufferWaterMark;
|
||||||
import io.netty.channel.epoll.EpollChannelOption;
|
|
||||||
import io.netty.channel.epoll.EpollDatagramChannel;
|
import io.netty.channel.epoll.EpollDatagramChannel;
|
||||||
import io.netty.channel.epoll.EpollEventLoopGroup;
|
import io.netty.channel.epoll.EpollEventLoopGroup;
|
||||||
import io.netty.channel.epoll.EpollServerSocketChannel;
|
import io.netty.channel.epoll.EpollServerSocketChannel;
|
||||||
@ -43,7 +42,6 @@ import io.netty.channel.socket.nio.NioDatagramChannel;
|
|||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
import io.netty.channel.socket.oio.OioDatagramChannel;
|
import io.netty.channel.socket.oio.OioDatagramChannel;
|
||||||
import io.netty.channel.socket.oio.OioServerSocketChannel;
|
import io.netty.channel.socket.oio.OioServerSocketChannel;
|
||||||
import io.netty.channel.unix.UnixChannelOption;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* from: https://blog.cloudflare.com/how-the-consumer-product-safety-commission-is-inadvertently-behind-the-internets-largest-ddos-attacks/
|
* from: https://blog.cloudflare.com/how-the-consumer-product-safety-commission-is-inadvertently-behind-the-internets-largest-ddos-attacks/
|
||||||
@ -117,20 +115,21 @@ class DnsServer extends Shutdownable {
|
|||||||
|
|
||||||
if (OS.isAndroid()) {
|
if (OS.isAndroid()) {
|
||||||
// android ONLY supports OIO (not NIO)
|
// android ONLY supports OIO (not NIO)
|
||||||
boss = new OioEventLoopGroup(0, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
boss = new OioEventLoopGroup(DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
||||||
worker = new OioEventLoopGroup(0, new NamedThreadFactory(threadName, threadGroup));
|
worker = new OioEventLoopGroup(DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
||||||
}
|
}
|
||||||
else if (OS.isLinux()) {
|
else if (OS.isLinux() && NativeLibrary.isAvailable()) {
|
||||||
// JNI network stack is MUCH faster (but only on linux)
|
// JNI network stack is MUCH faster (but only on linux)
|
||||||
boss = new EpollEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
boss = new EpollEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
||||||
worker = new EpollEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
worker = new EpollEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
||||||
}
|
}
|
||||||
else if (OS.isMacOsX()) {
|
else if (OS.isMacOsX() && NativeLibrary.isAvailable()) {
|
||||||
// KQueue network stack is MUCH faster (but only on macosx)
|
// KQueue network stack is MUCH faster (but only on macosx)
|
||||||
boss = new KQueueEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
boss = new KQueueEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
||||||
worker = new KQueueEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
worker = new KQueueEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// sometimes the native libraries cannot be loaded, so fall back to NIO
|
||||||
boss = new NioEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
boss = new NioEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
||||||
worker = new NioEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
worker = new NioEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
||||||
}
|
}
|
||||||
@ -148,11 +147,11 @@ class DnsServer extends Shutdownable {
|
|||||||
// android ONLY supports OIO (not NIO)
|
// android ONLY supports OIO (not NIO)
|
||||||
tcpBootstrap.channel(OioServerSocketChannel.class);
|
tcpBootstrap.channel(OioServerSocketChannel.class);
|
||||||
}
|
}
|
||||||
else if (OS.isLinux()) {
|
else if (OS.isLinux() && NativeLibrary.isAvailable()) {
|
||||||
// JNI network stack is MUCH faster (but only on linux)
|
// JNI network stack is MUCH faster (but only on linux)
|
||||||
tcpBootstrap.channel(EpollServerSocketChannel.class);
|
tcpBootstrap.channel(EpollServerSocketChannel.class);
|
||||||
}
|
}
|
||||||
else if (OS.isMacOsX()) {
|
else if (OS.isMacOsX() && NativeLibrary.isAvailable()) {
|
||||||
// KQueue network stack is MUCH faster (but only on macosx)
|
// KQueue network stack is MUCH faster (but only on macosx)
|
||||||
tcpBootstrap.channel(KQueueServerSocketChannel.class);
|
tcpBootstrap.channel(KQueueServerSocketChannel.class);
|
||||||
}
|
}
|
||||||
@ -165,7 +164,6 @@ class DnsServer extends Shutdownable {
|
|||||||
|
|
||||||
tcpBootstrap.group(boss, worker)
|
tcpBootstrap.group(boss, worker)
|
||||||
.option(ChannelOption.SO_BACKLOG, backlogConnectionCount)
|
.option(ChannelOption.SO_BACKLOG, backlogConnectionCount)
|
||||||
.option(ChannelOption.SO_REUSEADDR, true)
|
|
||||||
.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
|
.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
|
||||||
.childOption(ChannelOption.SO_KEEPALIVE, true)
|
.childOption(ChannelOption.SO_KEEPALIVE, true)
|
||||||
.option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(EndPoint.WRITE_BUFF_LOW, EndPoint.WRITE_BUFF_HIGH))
|
.option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(EndPoint.WRITE_BUFF_LOW, EndPoint.WRITE_BUFF_HIGH))
|
||||||
@ -191,13 +189,11 @@ class DnsServer extends Shutdownable {
|
|||||||
}
|
}
|
||||||
else if (OS.isLinux()) {
|
else if (OS.isLinux()) {
|
||||||
// JNI network stack is MUCH faster (but only on linux)
|
// JNI network stack is MUCH faster (but only on linux)
|
||||||
udpBootstrap.channel(EpollDatagramChannel.class)
|
udpBootstrap.channel(EpollDatagramChannel.class);
|
||||||
.option(EpollChannelOption.SO_REUSEPORT, true);
|
|
||||||
}
|
}
|
||||||
else if (OS.isMacOsX()) {
|
else if (OS.isMacOsX()) {
|
||||||
// JNI network stack is MUCH faster (but only on macosx)
|
// JNI network stack is MUCH faster (but only on macosx)
|
||||||
udpBootstrap.channel(KQueueDatagramChannel.class)
|
udpBootstrap.channel(KQueueDatagramChannel.class);
|
||||||
.option(UnixChannelOption.SO_REUSEPORT, true);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
udpBootstrap.channel(NioDatagramChannel.class);
|
udpBootstrap.channel(NioDatagramChannel.class);
|
||||||
|
144
src/dorkbox/network/NativeLibrary.java
Normal file
144
src/dorkbox/network/NativeLibrary.java
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 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;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
import dorkbox.util.NativeLoader;
|
||||||
|
import dorkbox.util.OS;
|
||||||
|
import io.netty.channel.epoll.Epoll;
|
||||||
|
import io.netty.channel.kqueue.KQueue;
|
||||||
|
import io.netty.util.internal.PlatformDependent;
|
||||||
|
import io.netty.util.internal.SystemPropertyUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public
|
||||||
|
class NativeLibrary {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to extract the native transport libraries for Linux/MacOsX into a "semi-permanent" location. If this is unsuccessful for any
|
||||||
|
* reason, netty will fall back to it's own logic.
|
||||||
|
*/
|
||||||
|
static {
|
||||||
|
if (OS.isLinux() || OS.isMacOsX()) {
|
||||||
|
// try to load the native libraries for Linux/MacOsX...
|
||||||
|
String originalLibraryPath = SystemPropertyUtil.get("java.library.path");
|
||||||
|
File outputDirectory;
|
||||||
|
|
||||||
|
String workdir = SystemPropertyUtil.get("io.netty.native.workdir");
|
||||||
|
if (workdir != null) {
|
||||||
|
File f = new File(workdir);
|
||||||
|
if (!f.isDirectory()) {
|
||||||
|
f.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
f = f.getAbsoluteFile();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
// Good to have an absolute path, but it's OK.
|
||||||
|
}
|
||||||
|
|
||||||
|
outputDirectory = f;
|
||||||
|
// logger.debug("-Dio.netty.native.workdir: " + WORKDIR);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
outputDirectory = PlatformDependent.tmpdir();
|
||||||
|
// logger.debug("-Dio.netty.native.workdir: " + WORKDIR + " (io.netty.tmpdir)");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
System.setProperty("java.library.path", originalLibraryPath + File.pathSeparator + outputDirectory.getAbsolutePath());
|
||||||
|
|
||||||
|
// reset the classloader library path.
|
||||||
|
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
|
||||||
|
fieldSysPath.setAccessible(true);
|
||||||
|
fieldSysPath.set(null, null);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String staticLibName;
|
||||||
|
if (OS.isLinux()) {
|
||||||
|
staticLibName = "netty_transport_native_epoll";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
staticLibName = "netty_transport_native_kqueue";
|
||||||
|
}
|
||||||
|
|
||||||
|
staticLibName = "lib" + staticLibName + '_' + PlatformDependent.normalizedArch();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
String jarLibName = "META-INF/native/" + staticLibName;
|
||||||
|
if (OS.isLinux()) {
|
||||||
|
jarLibName += ".so";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
jarLibName += ".jnilib";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
NativeLoader.extractLibrary(jarLibName, outputDirectory.getAbsolutePath(), staticLibName, null);
|
||||||
|
|
||||||
|
// we have to try to load the native library HERE, while the java.library.path has it
|
||||||
|
if (OS.isLinux()) {
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
Epoll.isAvailable();
|
||||||
|
}
|
||||||
|
else if (OS.isMacOsX()) {
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
KQueue.isAvailable();
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
System.setProperty("java.library.path", originalLibraryPath);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// reset the classloader library path.
|
||||||
|
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
|
||||||
|
fieldSysPath.setAccessible(true);
|
||||||
|
fieldSysPath.set(null, null);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// either not Linux/MacOsX, or loading the library failed.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the (possibly) required native libraries have been loaded
|
||||||
|
*/
|
||||||
|
public static
|
||||||
|
boolean isAvailable() {
|
||||||
|
if (OS.isLinux()) {
|
||||||
|
return Epoll.isAvailable();
|
||||||
|
}
|
||||||
|
else if (OS.isMacOsX()) {
|
||||||
|
return KQueue.isAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
// not Linux/MacOsX
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -46,7 +46,6 @@ import io.netty.channel.socket.nio.NioDatagramChannel;
|
|||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
import io.netty.channel.socket.oio.OioDatagramChannel;
|
import io.netty.channel.socket.oio.OioDatagramChannel;
|
||||||
import io.netty.channel.socket.oio.OioServerSocketChannel;
|
import io.netty.channel.socket.oio.OioServerSocketChannel;
|
||||||
import io.netty.channel.unix.UnixChannelOption;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The server can only be accessed in an ASYNC manner. This means that the server can only be used in RESPONSE to events. If you access the
|
* The server can only be accessed in an ASYNC manner. This means that the server can only be used in RESPONSE to events. If you access the
|
||||||
@ -151,15 +150,15 @@ class Server<C extends Connection> extends EndPointServer {
|
|||||||
|
|
||||||
if (OS.isAndroid()) {
|
if (OS.isAndroid()) {
|
||||||
// android ONLY supports OIO (not NIO)
|
// android ONLY supports OIO (not NIO)
|
||||||
boss = new OioEventLoopGroup(0, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
boss = new OioEventLoopGroup(DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
||||||
worker = new OioEventLoopGroup(0, new NamedThreadFactory(threadName, threadGroup));
|
worker = new OioEventLoopGroup(DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
||||||
}
|
}
|
||||||
else if (OS.isLinux()) {
|
else if (OS.isLinux() && NativeLibrary.isAvailable()) {
|
||||||
// JNI network stack is MUCH faster (but only on linux)
|
// JNI network stack is MUCH faster (but only on linux)
|
||||||
boss = new EpollEventLoopGroup(DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
boss = new EpollEventLoopGroup(DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
||||||
worker = new EpollEventLoopGroup(DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
worker = new EpollEventLoopGroup(DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
||||||
}
|
}
|
||||||
else if (OS.isMacOsX()) {
|
else if (OS.isMacOsX() && NativeLibrary.isAvailable()) {
|
||||||
// KQueue network stack is MUCH faster (but only on macosx)
|
// KQueue network stack is MUCH faster (but only on macosx)
|
||||||
boss = new KQueueEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
boss = new KQueueEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
||||||
worker = new KQueueEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
worker = new KQueueEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
||||||
@ -200,12 +199,12 @@ class Server<C extends Connection> extends EndPointServer {
|
|||||||
// android ONLY supports OIO (not NIO)
|
// android ONLY supports OIO (not NIO)
|
||||||
tcpBootstrap.channel(OioServerSocketChannel.class);
|
tcpBootstrap.channel(OioServerSocketChannel.class);
|
||||||
}
|
}
|
||||||
else if (OS.isLinux()) {
|
else if (OS.isLinux() && NativeLibrary.isAvailable()) {
|
||||||
// JNI network stack is MUCH faster (but only on linux)
|
// JNI network stack is MUCH faster (but only on linux)
|
||||||
tcpBootstrap.channel(EpollServerSocketChannel.class);
|
tcpBootstrap.channel(EpollServerSocketChannel.class);
|
||||||
}
|
}
|
||||||
else if (OS.isMacOsX()) {
|
else if (OS.isMacOsX() && NativeLibrary.isAvailable()) {
|
||||||
// JNI network stack is MUCH faster (but only on macosx)
|
// KQueue network stack is MUCH faster (but only on macosx)
|
||||||
tcpBootstrap.channel(KQueueServerSocketChannel.class);
|
tcpBootstrap.channel(KQueueServerSocketChannel.class);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -243,18 +242,15 @@ class Server<C extends Connection> extends EndPointServer {
|
|||||||
if (udpBootstrap != null) {
|
if (udpBootstrap != null) {
|
||||||
if (OS.isAndroid()) {
|
if (OS.isAndroid()) {
|
||||||
// android ONLY supports OIO (not NIO)
|
// android ONLY supports OIO (not NIO)
|
||||||
udpBootstrap.channel(OioDatagramChannel.class)
|
udpBootstrap.channel(OioDatagramChannel.class);
|
||||||
.option(UnixChannelOption.SO_REUSEPORT, true);
|
|
||||||
}
|
}
|
||||||
else if (OS.isLinux()) {
|
else if (OS.isLinux() && NativeLibrary.isAvailable()) {
|
||||||
// JNI network stack is MUCH faster (but only on linux)
|
// JNI network stack is MUCH faster (but only on linux)
|
||||||
udpBootstrap.channel(EpollDatagramChannel.class)
|
udpBootstrap.channel(EpollDatagramChannel.class);
|
||||||
.option(UnixChannelOption.SO_REUSEPORT, true);
|
|
||||||
}
|
}
|
||||||
else if (OS.isMacOsX()) {
|
else if (OS.isMacOsX() && NativeLibrary.isAvailable()) {
|
||||||
// JNI network stack is MUCH faster (but only on macosx)
|
// KQueue network stack is MUCH faster (but only on macosx)
|
||||||
udpBootstrap.channel(KQueueDatagramChannel.class)
|
udpBootstrap.channel(KQueueDatagramChannel.class);
|
||||||
.option(UnixChannelOption.SO_REUSEPORT, true);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// windows
|
// windows
|
||||||
|
Loading…
Reference in New Issue
Block a user