Yatopia/patches/server/0060-New-Network-System.patch
Simon Gardling d059af01b6
Updated Upstream and Sidestream(s) (Paper/Purpur/AirplaneLite) (#362)
* Updated Upstream and Sidestream(s) (Paper/Purpur/AirplaneLite)

Upstream/An Sidestream has released updates that appears to apply and compile correctly
This update has NOT been tested by YatopiaMC and as with ANY update, please do your own testing.

Paper Changes:
fc4c0bc42 Reset shield blocking on dimension change
1c8b6065e Skip distance map update when spawning is disabled
091e6700f Added PlayerStonecutterRecipeSelectEvent
fc885f966 Add toggle for always placing the dragon egg
b3a6da3a7 Updated Upstream (Bukkit/CraftBukkit)
18ccc062d [Auto] Updated Upstream (Spigot)

Purpur Changes:
df9bd08 Config to use infinity bows without arrows (#149)
9d537bc Fix PlayerEditBookEvent not saving new book
3f8816d [ci-skip] Oops
5508728 [ci-skip] Add granny to funding
4c7ab70 Updated Upstream (Paper)
5eefb52 [ci-skip] Update Gradle to 6.8.1

AirplaneLite Changes:
459bb20 Remove patch
515fec7 Remove streams
fc94d7b Correct launcher name
0b153bd Update gradle version

* add Remove-streams.patch from AirplaneLite
2021-01-25 13:22:51 -06:00

320 lines
14 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hugo Planque <hookwood01@gmail.com>
Date: Mon, 18 Jan 2021 11:27:08 +0100
Subject: [PATCH] New Network System
Co-authored-by: Ivan Pekov <ivan@mrivanplays.com>
diff --git a/pom.xml b/pom.xml
index 8af1a91102c5cc4c230f622e6629e46e95f17d44..9b7ed0de1054285dadff6aefc95c7207079504a6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -53,9 +53,17 @@
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
- <version>4.1.50.Final</version>
+ <version>4.1.58.Final</version> <!-- Yatopia -->
</dependency>
<!-- Tuinity end - fix compile issue (cannot see new api) by moving netty include BEFORE server jar -->
+ <!-- Yatopia start - Add IOUring beta support -->
+ <dependency>
+ <groupId>io.netty.incubator</groupId>
+ <artifactId>netty-incubator-transport-native-io_uring</artifactId>
+ <version>0.0.3.Final</version>
+ <classifier>linux-x86_64</classifier>
+ </dependency>
+ <!-- Yatopia end -->
<dependency>
<groupId>io.papermc</groupId>
<artifactId>minecraft-server</artifactId>
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 87cf9cd88d1fb5ae70d19e5618ebfb67d281304a..a1c2bea7c93433434b4e4dfd0bb4b9620657c40d 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1740,6 +1740,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
return true;
}
+ public final boolean isUsingNativeTransport() { return l(); } // Yatopia - OBFHELPER
public abstract boolean l();
public boolean getPVP() {
diff --git a/src/main/java/net/minecraft/server/ServerConnection.java b/src/main/java/net/minecraft/server/ServerConnection.java
index 0668d383db1f3a81d1053954d72678c7ac5aecec..d22f0ee3f7f2daa8323d454aca1f94733b249333 100644
--- a/src/main/java/net/minecraft/server/ServerConnection.java
+++ b/src/main/java/net/minecraft/server/ServerConnection.java
@@ -11,6 +11,7 @@ import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.Epoll;
+import io.netty.channel.epoll.EpollChannelOption; // Yatopia
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
@@ -26,6 +27,7 @@ import java.util.List;
import javax.annotation.Nullable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.yatopiamc.yatopia.server.network.NetworkType; // Yatopia
public class ServerConnection {
@@ -52,15 +54,29 @@ public class ServerConnection {
}
// Paper end
+ // Yatopia start - New network system
+ private final NetworkType networkType;
+ private final EventLoopGroup boss, worker;
+ // Yatopia end
+
public ServerConnection(MinecraftServer minecraftserver) {
this.e = minecraftserver;
this.c = true;
+
+ // Yatopia start - New network system
+ this.networkType = NetworkType.bestType(minecraftserver, LOGGER);
+ this.boss = networkType.createEventLoopGroup(NetworkType.LoopGroupType.BOSS);
+ this.worker = networkType.createEventLoopGroup(NetworkType.LoopGroupType.WORKER);
+ // Yatopia end
}
public void a(@Nullable InetAddress inetaddress, int i) throws IOException {
+ /* // Yatopia start - New network system
List list = this.listeningChannels;
+ */
synchronized (this.listeningChannels) {
+ /*
Class oclass;
LazyInitVar lazyinitvar;
@@ -73,16 +89,25 @@ public class ServerConnection {
lazyinitvar = ServerConnection.a;
ServerConnection.LOGGER.info("Using default channel type");
}
+ */
+
// Tuinity start - indicate Velocity natives in use
ServerConnection.LOGGER.info("Tuinity: Using " + com.velocitypowered.natives.util.Natives.compress.getLoadedVariant() + " compression from Velocity.");
ServerConnection.LOGGER.info("Tuinity: Using " + com.velocitypowered.natives.util.Natives.cipher.getLoadedVariant() + " cipher from Velocity.");
// Tuinity end
- this.listeningChannels.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(oclass)).childHandler(new ChannelInitializer<Channel>() {
+ ServerConnection.LOGGER.info("Yatopia: Using " + networkType.getName() + " network type.");
+ ServerBootstrap serverBootstrap = new ServerBootstrap();
+
+ if (org.yatopiamc.yatopia.server.YatopiaConfig.tcpFastOpen && networkType == NetworkType.EPOLL) {
+ serverBootstrap.option(EpollChannelOption.TCP_FASTOPEN, 3); // Will improve the connection with some speed
+ }
+ this.listeningChannels.add((((serverBootstrap).channelFactory(networkType.getServerSocketChannelFactory())).childHandler(new ChannelInitializer<Channel>() {
protected void initChannel(Channel channel) throws Exception {
try {
channel.config().setOption(ChannelOption.TCP_NODELAY, true);
+ channel.config().setOption(ChannelOption.IP_TOS, 0x18); // Change the priority of the packet to immediate
} catch (ChannelException channelexception) {
;
}
@@ -97,7 +122,8 @@ public class ServerConnection {
channel.pipeline().addLast("packet_handler", (ChannelHandler) object);
((NetworkManager) object).setPacketListener(new HandshakeListener(ServerConnection.this.e, (NetworkManager) object));
}
- }).group((EventLoopGroup) lazyinitvar.a()).localAddress(inetaddress, i)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit
+ }).group(boss, worker).localAddress(inetaddress, i)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit
+ // Yatopia end
}
}
diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
index c2dc5265552ebd429111253c70481003a4be29dd..c67654e8701b9da6499d442048429149daae7150 100644
--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
+++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
@@ -271,4 +271,17 @@ public class YatopiaConfig {
logPlayerLoginLoc = getBoolean("settings.log-player-login-location", logPlayerLoginLoc);
}
+ public static boolean ioUringBeta = false;
+ public static boolean tcpFastOpen = false;
+ public static boolean debugNetwork = false;
+ private static void newNetworkSystem() {
+ ioUringBeta = getBoolean("network.io-uring", ioUringBeta);
+ if (config.get("network.ftcp-fastopen") != null) {
+ config.set("network.tcp-fastopen", getBoolean("network.ftcp-fastopen", tcpFastOpen));
+ config.set("network.ftcp-fastopen", null);
+ }
+ tcpFastOpen = getBoolean("network.tcp-fastopen", tcpFastOpen);
+ debugNetwork = getBoolean("network.debug", debugNetwork);
+ }
+
}
diff --git a/src/main/java/org/yatopiamc/yatopia/server/network/NettyThreadFactory.java b/src/main/java/org/yatopiamc/yatopia/server/network/NettyThreadFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..3e74e23f3cc44b7547d9f8575b411059e0e65449
--- /dev/null
+++ b/src/main/java/org/yatopiamc/yatopia/server/network/NettyThreadFactory.java
@@ -0,0 +1,27 @@
+package org.yatopiamc.yatopia.server.network;
+
+import io.netty.util.concurrent.FastThreadLocalThread;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Based off of Velocity's VelocityNettyThreadFactory
+ */
+public class NettyThreadFactory implements ThreadFactory {
+
+ private final AtomicInteger threadNumber = new AtomicInteger();
+ private final String networkTypeName, loopGroupTypeName;
+
+ public NettyThreadFactory(String networkTypeName, String loopGroupTypeName) {
+ this.networkTypeName = networkTypeName;
+ this.loopGroupTypeName = loopGroupTypeName;
+ }
+
+ @Override
+ public Thread newThread(Runnable r) {
+ return new FastThreadLocalThread(
+ r,
+ "Netty " + networkTypeName + " " + loopGroupTypeName + " #" + threadNumber.getAndIncrement()
+ );
+ }
+}
diff --git a/src/main/java/org/yatopiamc/yatopia/server/network/NetworkType.java b/src/main/java/org/yatopiamc/yatopia/server/network/NetworkType.java
new file mode 100644
index 0000000000000000000000000000000000000000..6c387f29e4db7e1574a2bbb119465c48b8ed2f90
--- /dev/null
+++ b/src/main/java/org/yatopiamc/yatopia/server/network/NetworkType.java
@@ -0,0 +1,129 @@
+package org.yatopiamc.yatopia.server.network;
+
+import io.netty.channel.ChannelFactory;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.epoll.Epoll;
+import io.netty.channel.epoll.EpollEventLoopGroup;
+import io.netty.channel.epoll.EpollServerSocketChannel;
+import io.netty.channel.kqueue.KQueue;
+import io.netty.channel.kqueue.KQueueEventLoopGroup;
+import io.netty.channel.kqueue.KQueueServerSocketChannel;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.ServerSocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.incubator.channel.uring.IOUring;
+import io.netty.incubator.channel.uring.IOUringEventLoopGroup;
+import io.netty.incubator.channel.uring.IOUringServerSocketChannel;
+
+import java.util.concurrent.ThreadFactory;
+import java.util.function.BiFunction;
+
+import net.minecraft.server.MinecraftServer;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Logger;
+import org.spigotmc.SpigotConfig;
+import org.yatopiamc.yatopia.server.YatopiaConfig;
+
+/**
+ * Based off of Velocity's TransportType
+ */
+public enum NetworkType {
+ NIO("NIO", NioServerSocketChannel::new, (name, type) -> new NioEventLoopGroup(8, createThreadFactory(name, type))),
+
+ EPOLL("Epoll", EpollServerSocketChannel::new, (name, type) -> new EpollEventLoopGroup(8, createThreadFactory(name, type))),
+
+ IOURING("IOUring", IOUringServerSocketChannel::new, (name, type) -> new IOUringEventLoopGroup(8, createThreadFactory(name, type))),
+
+ KQUEUE("KQueue", KQueueServerSocketChannel::new, (name, type) -> new KQueueEventLoopGroup(8, createThreadFactory(name, type)));
+
+ public final String name;
+ public final ChannelFactory<? extends ServerSocketChannel> serverSocketChannelFactory;
+ public final BiFunction<String, LoopGroupType, EventLoopGroup> eventLoopGroupFactory;
+
+ NetworkType(final String name,
+ final ChannelFactory<? extends ServerSocketChannel> serverSocketChannelFactory,
+ final BiFunction<String, LoopGroupType, EventLoopGroup> eventLoopGroupFactory) {
+ this.name = name;
+ this.serverSocketChannelFactory = serverSocketChannelFactory;
+ this.eventLoopGroupFactory = eventLoopGroupFactory;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public ChannelFactory<? extends ServerSocketChannel> getServerSocketChannelFactory() {
+ return serverSocketChannelFactory;
+ }
+
+ @Override
+ public String toString() {
+ return this.name;
+ }
+
+ public EventLoopGroup createEventLoopGroup(final LoopGroupType type) {
+ return this.eventLoopGroupFactory.apply(this.name, type);
+ }
+
+ private static ThreadFactory createThreadFactory(final String name, final LoopGroupType type) {
+ return new NettyThreadFactory(name, type.toString());
+ }
+
+ public static NetworkType bestType(MinecraftServer minecraftServer, Logger logger) {
+ if (!minecraftServer.isUsingNativeTransport()) {
+ return NIO;
+ }
+ // Actually, there is a decompression problem with zlib from bungeecord that makes
+ // IOUring not available on spigot server with bungeecord
+ // https://github.com/netty/netty-incubator-transport-io_uring/issues/40
+ // Looks like iouring send very small compressed packet and trigger PacketDecompressor
+ if (!SpigotConfig.bungee && YatopiaConfig.ioUringBeta && MinecraftServer.getServer().ax() < 0) {
+ if (IOUring.isAvailable()) {
+ return IOURING;
+ } else if (YatopiaConfig.debugNetwork) {
+ logger.log(Level.ERROR, "IOUring is not working: {}", exceptionMessage(IOUring.unavailabilityCause()));
+ }
+ }
+
+ if (Epoll.isAvailable()) {
+ return EPOLL;
+ } else if (YatopiaConfig.debugNetwork) {
+ logger.log(Level.ERROR, "Epoll is not working: {}", exceptionMessage(Epoll.unavailabilityCause()));
+ }
+
+ if (KQueue.isAvailable()) {
+ return KQUEUE;
+ } else if (YatopiaConfig.debugNetwork) {
+ logger.log(Level.ERROR, "KQueue is not working: {}", exceptionMessage(KQueue.unavailabilityCause()));
+ }
+
+ return NIO;
+ }
+
+ private static String exceptionMessage(Throwable throwable) {
+ StackTraceElement[] trace = throwable.getStackTrace();
+ return getClassNameFromString(throwable.getClass().getName()) + " : " + throwable.getMessage() +
+ ((trace.length > 0) ? " @ " + throwable.getStackTrace()[0].getClassName() + ":" + throwable.getStackTrace()[0].getLineNumber() : "");
+ }
+
+ private static String getClassNameFromString(String className) {
+ int i = className.lastIndexOf('.');
+ return i > 0 ? className.substring(i + 1) : className;
+ }
+
+ public enum LoopGroupType {
+ BOSS("Boss"),
+ WORKER("Worker");
+
+ private final String name;
+
+ LoopGroupType(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return this.name;
+ }
+ }
+}