fix using epoll under linux, improved netty native handling

This commit is contained in:
Bixilon 2022-05-28 19:36:23 +02:00
parent 574c71f359
commit 06f3a89a7b
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
7 changed files with 110 additions and 32 deletions

27
pom.xml
View File

@ -151,6 +151,7 @@
<lwjgl.natives>linux</lwjgl.natives>
<zstd.natives>linux_amd64</zstd.natives>
<javafx.natives>linux</javafx.natives>
<netty.natives.epoll>x86_64</netty.natives.epoll>
</properties>
</profile>
<profile>
@ -165,6 +166,7 @@
<lwjgl.natives>linux-arm64</lwjgl.natives>
<zstd.natives>linux_aarch64</zstd.natives>
<javafx.natives>linux-aarch64</javafx.natives>
<netty.natives.epoll>aarch64</netty.natives.epoll>
</properties>
</profile>
<profile>
@ -237,6 +239,23 @@
<javafx.natives>win-x86</javafx.natives>
</properties>
</profile>
<profile>
<id>natives-windows-x86</id>
<activation>
<os>
<family>unix</family>
</os>
</activation>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<version>${netty.version}</version>
<classifier>linux-${netty.natives.epoll}</classifier>
</dependency>
</dependencies>
</profile>
</profiles>
@ -470,19 +489,11 @@
<groupId>io.netty</groupId>
<artifactId>netty-buffer</artifactId>
<version>${netty.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<version>${netty.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
<version>${netty.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>it.unimi.dsi</groupId>

View File

@ -38,7 +38,7 @@ class OtherProfile(
/**
* Use native network transport if available
*/
var epoll by delegate(true)
var nativeNetwork by delegate(true)
/**

View File

@ -186,7 +186,7 @@ class PlayConnection(
renderLatch.awaitWithChange()
}
Log.log(LogMessageType.NETWORK_STATUS, level = LogLevels.INFO) { "Connecting to server: $address" }
network.connect(address, profiles.other.epoll)
network.connect(address, profiles.other.nativeNetwork)
state = PlayConnectionStates.ESTABLISHING
} catch (exception: Throwable) {
Log.log(LogMessageType.VERSION_LOADING, level = LogLevels.FATAL) { exception }

View File

@ -24,6 +24,8 @@ import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.network.connection.status.StatusConnection
import de.bixilon.minosoft.protocol.network.network.client.exceptions.NetworkException
import de.bixilon.minosoft.protocol.network.network.client.exceptions.ciritical.CriticalNetworkException
import de.bixilon.minosoft.protocol.network.network.client.natives.NioNatives
import de.bixilon.minosoft.protocol.network.network.client.natives.TransportNatives
import de.bixilon.minosoft.protocol.network.network.client.pipeline.compression.PacketDeflater
import de.bixilon.minosoft.protocol.network.network.client.pipeline.compression.PacketInflater
import de.bixilon.minosoft.protocol.network.network.client.pipeline.encryption.PacketDecryptor
@ -39,11 +41,6 @@ import de.bixilon.minosoft.util.logging.LogLevels
import de.bixilon.minosoft.util.logging.LogMessageType
import io.netty.bootstrap.Bootstrap
import io.netty.channel.*
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 io.netty.handler.codec.DecoderException
import io.netty.handler.codec.EncoderException
import javax.crypto.Cipher
@ -91,20 +88,12 @@ class NettyClient(
private val packetQueue: MutableList<C2SPacket> = mutableListOf() // Used for pause sending
private var sendingPaused = false
fun connect(address: ServerAddress, epoll: Boolean) {
fun connect(address: ServerAddress, native: Boolean) {
state = ProtocolStates.HANDSHAKING
val threadPool: EventLoopGroup
val channelClass: Class<out Channel>
if (epoll && Epoll.isAvailable()) {
threadPool = EPOLL_THREAD_POOL
channelClass = EpollSocketChannel::class.java
} else {
threadPool = NIO_THREAD_POOL
channelClass = NioSocketChannel::class.java
}
val natives = if (native) TransportNatives.get() else NioNatives
val bootstrap = Bootstrap()
.group(threadPool)
.channel(channelClass)
.group(natives.pool)
.channel(natives.channel)
.handler(NetworkPipeline(this))
val future = bootstrap.connect(address.hostname, address.port)
@ -212,9 +201,4 @@ class NettyClient(
}
return channel
}
companion object {
private val NIO_THREAD_POOL by lazy { NioEventLoopGroup(NamedThreadFactory("Nio#%d")) }
private val EPOLL_THREAD_POOL by lazy { EpollEventLoopGroup(NamedThreadFactory("Epoll#%d")) }
}
}

View File

@ -0,0 +1,24 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.protocol.network.network.client.natives
import de.bixilon.minosoft.protocol.network.network.client.NamedThreadFactory
import io.netty.channel.Channel
import io.netty.channel.epoll.EpollEventLoopGroup
import io.netty.channel.epoll.EpollSocketChannel
object EpollNatives : TransportNatives {
override val pool by lazy { EpollEventLoopGroup(NamedThreadFactory("Epoll#%d")) }
override val channel: Class<out Channel> = EpollSocketChannel::class.java
}

View File

@ -0,0 +1,24 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.protocol.network.network.client.natives
import de.bixilon.minosoft.protocol.network.network.client.NamedThreadFactory
import io.netty.channel.Channel
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.nio.NioSocketChannel
object NioNatives : TransportNatives {
override val pool by lazy { NioEventLoopGroup(NamedThreadFactory("Nio#%d")) }
override val channel: Class<out Channel> = NioSocketChannel::class.java
}

View File

@ -0,0 +1,35 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.protocol.network.network.client.natives
import io.netty.channel.Channel
import io.netty.channel.EventLoopGroup
import io.netty.channel.epoll.Epoll
interface TransportNatives {
val pool: EventLoopGroup
val channel: Class<out Channel>
companion object {
fun get(): TransportNatives {
if (Epoll.isAvailable()) {
return EpollNatives
}
return NioNatives
}
}
}