diff --git a/src/main/java/de/bixilon/minosoft/config/profile/profiles/other/OtherProfile.kt b/src/main/java/de/bixilon/minosoft/config/profile/profiles/other/OtherProfile.kt
index 09056b702..62a2c4969 100644
--- a/src/main/java/de/bixilon/minosoft/config/profile/profiles/other/OtherProfile.kt
+++ b/src/main/java/de/bixilon/minosoft/config/profile/profiles/other/OtherProfile.kt
@@ -35,6 +35,11 @@ class OtherProfile(
override val version: Int = latestVersion
override var description by delegate(description ?: "")
+ /**
+ * Use native network transport if available
+ */
+ var epoll by delegate(true)
+
/**
* MacOS only: Ignores the warning if the jvm argument
diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt b/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt
index fea39fe26..8928710ec 100644
--- a/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt
+++ b/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt
@@ -224,7 +224,7 @@ class PlayConnection(
renderLatch.awaitWithChange()
}
Log.log(LogMessageType.NETWORK_STATUS, level = LogLevels.INFO) { "Connecting to server: $address" }
- network.connect(address)
+ network.connect(address, profiles.other.epoll)
state = PlayConnectionStates.ESTABLISHING
} catch (exception: Throwable) {
Log.log(LogMessageType.VERSION_LOADING, level = LogLevels.FATAL) { exception }
diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/connection/status/StatusConnection.kt b/src/main/java/de/bixilon/minosoft/protocol/network/connection/status/StatusConnection.kt
index 3938ef24c..b61aa9232 100644
--- a/src/main/java/de/bixilon/minosoft/protocol/network/connection/status/StatusConnection.kt
+++ b/src/main/java/de/bixilon/minosoft/protocol/network/connection/status/StatusConnection.kt
@@ -143,7 +143,7 @@ class StatusConnection(
Log.log(LogMessageType.NETWORK_RESOLVING) { "Trying to ping $tryAddress (from $address)" }
state = StatusConnectionStates.ESTABLISHING
- network.connect(tryAddress)
+ network.connect(tryAddress, false)
}
}
diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/network/client/NamedThreadFactory.kt b/src/main/java/de/bixilon/minosoft/protocol/network/network/client/NamedThreadFactory.kt
new file mode 100644
index 000000000..2230ef77f
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/protocol/network/network/client/NamedThreadFactory.kt
@@ -0,0 +1,27 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.protocol.network.network.client
+
+import java.util.concurrent.ThreadFactory
+import java.util.concurrent.atomic.AtomicInteger
+
+class NamedThreadFactory(
+ val format: String,
+) : ThreadFactory {
+ var count = AtomicInteger(0)
+
+ override fun newThread(runnable: Runnable): Thread {
+ return Thread(runnable, format.format(count.incrementAndGet()))
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/network/client/NettyClient.kt b/src/main/java/de/bixilon/minosoft/protocol/network/network/client/NettyClient.kt
index ae73d390a..a799a9f94 100644
--- a/src/main/java/de/bixilon/minosoft/protocol/network/network/client/NettyClient.kt
+++ b/src/main/java/de/bixilon/minosoft/protocol/network/network/client/NettyClient.kt
@@ -14,7 +14,6 @@
package de.bixilon.minosoft.protocol.network.network.client
import de.bixilon.kutil.cast.CastUtil.nullCast
-import de.bixilon.kutil.concurrent.pool.DefaultThreadPool
import de.bixilon.kutil.watcher.DataWatcher.Companion.watched
import de.bixilon.minosoft.config.profile.profiles.other.OtherProfileManager
import de.bixilon.minosoft.protocol.network.connection.Connection
@@ -32,6 +31,10 @@ import io.netty.bootstrap.Bootstrap
import io.netty.channel.Channel
import io.netty.channel.ChannelFuture
import io.netty.channel.ChannelOption
+import io.netty.channel.EventLoopGroup
+import io.netty.channel.epoll.Epoll
+import io.netty.channel.epoll.EpollEventLoopGroup
+import io.netty.channel.epoll.EpollSocketChannel
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.nio.NioSocketChannel
import javax.crypto.Cipher
@@ -69,12 +72,19 @@ class NettyClient(
private set
private var channel: Channel? = null
- fun connect(address: ServerAddress) {
- val workerGroup = NioEventLoopGroup(DefaultThreadPool.threadCount - 1, DefaultThreadPool)
- // val workerGroup = NioEventLoopGroup()
+ fun connect(address: ServerAddress, epoll: Boolean) {
+ val threadPool: EventLoopGroup
+ val channelClass: Class
+ if (Epoll.isAvailable() && epoll) {
+ threadPool = EPOLL_THREAD_POOL
+ channelClass = EpollSocketChannel::class.java
+ } else {
+ threadPool = NIO_THREAD_POOL
+ channelClass = NioSocketChannel::class.java
+ }
val bootstrap = Bootstrap()
- .group(workerGroup)
- .channel(NioSocketChannel::class.java)
+ .group(threadPool)
+ .channel(channelClass)
.handler(NetworkPipeline(this))
val future: ChannelFuture = bootstrap.connect(address.hostname, address.port).sync()
@@ -85,9 +95,11 @@ class NettyClient(
}
val channel = future.channel()
this.channel = channel
- channel.config().setOption(ChannelOption.TCP_NODELAY, true)
+ try {
+ channel.config().setOption(ChannelOption.TCP_NODELAY, true)
+ } catch (_: Throwable) {
+ }
connected = true
- println("Connected!")
}
}
@@ -103,7 +115,6 @@ class NettyClient(
fun disconnect() {
channel?.close()
- // ToDo: workerGroup.shutdownGracefully()
connected = false
}
@@ -119,4 +130,9 @@ class NettyClient(
packet.log((connection.nullCast()?.profiles?.other ?: OtherProfileManager.selected).log.reducedProtocolLog)
channel.writeAndFlush(packet)
}
+
+ companion object {
+ private val NIO_THREAD_POOL by lazy { NioEventLoopGroup(NamedThreadFactory("Nio#%d")) }
+ private val EPOLL_THREAD_POOL by lazy { EpollEventLoopGroup(NamedThreadFactory("Epoll#%d")) }
+ }
}