Skip to content
This repository has been archived by the owner on Jun 19, 2021. It is now read-only.

New network system #340

Merged
merged 18 commits into from
Jan 23, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions PATCHES.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ This is an overview over all patches that are currently used.
| server | Multi-Threaded Server Ticking Vanilla | Spottedleaf | |
| server | Multi-Threaded ticking CraftBukkit | Spottedleaf | |
| server | Name craft scheduler threads according to the plugin using | Spottedleaf | |
| server | New Network System | Hugo Planque | Ivan Pekov |
| server | Nuke streams off BlockPosition | Ivan Pekov | |
| server | Nuke streams off SectionPosition | Ivan Pekov | |
| server | Optimise EntityInsentient#checkDespawn | Spottedleaf | |
Expand Down Expand Up @@ -290,6 +291,7 @@ This is an overview over all patches that are currently used.
| server | PlayerSetSpawnerTypeWithEggEvent | William Blake Galbreath | |
| server | Players should not cram to death | William Blake Galbreath | |
| server | Populator seed controls | Spottedleaf | |
| server | Port krypton | Andrew Steinborn | |
| server | Prevent light queue overfill when no players are online | Spottedleaf | |
| server | Prevent long map entry creation in light engine | Spottedleaf | |
| server | Prevent unload() calls removing tickets for sync loads | Spottedleaf | |
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Yatopia combines the code from many [Paper](https://github.com/PaperMC/Paper) fo
* [Origami](https://github.com/Minebench/Origami)
* [Purpur](https://github.com/pl3xgaming/Purpur)
* [AirplaneLite](https://github.com/Technove/AirplaneLite)
* [Krypton](https://github.com/astei/krypton)


## Try it out
Expand Down
307 changes: 307 additions & 0 deletions patches/server/0066-New-Network-System.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,307 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hugo Planque <[email protected]>
Date: Mon, 18 Jan 2021 11:27:08 +0100
Subject: [PATCH] New Network System

Co-authored-by: Ivan Pekov <[email protected]>

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>
MrIvanPlays marked this conversation as resolved.
Show resolved Hide resolved
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..f20be527bec58bad8e4a5bb7bb887949cb6d1d99 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,16 +27,20 @@ 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 {

private static final Logger LOGGER = LogManager.getLogger();
+ /* // Yatopia Start - New network system - Remove unused fields
public static final LazyInitVar<NioEventLoopGroup> a = new LazyInitVar<>(() -> {
return new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Server IO #%d").setDaemon(true).build());
});
public static final LazyInitVar<EpollEventLoopGroup> b = new LazyInitVar<>(() -> {
return new EpollEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Epoll Server IO #%d").setDaemon(true).build());
});
+ */
+ // Yatopia end
private final MinecraftServer e;
public volatile boolean c;
private final List<ChannelFuture> listeningChannels = Collections.synchronizedList(Lists.newArrayList());
@@ -52,15 +57,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);
+ 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 +92,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 +125,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 35f212c2ac43ebea6ce9c4a333738c7a869ebc18..c4d0dabd408c7a943dafd6ca89b598cb4afb440e 100644
--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
+++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
@@ -303,4 +303,11 @@ public class YatopiaConfig {
logPlayerLoginLoc = getBoolean("settings.log-player-login-location", logPlayerLoginLoc);
}

+ public static boolean ioUringBeta = false;
+ public static boolean tcpFastOpen = false;
+ private static void newNetworkSystem() {
+ ioUringBeta = getBoolean("network.io-uring", ioUringBeta);
+ tcpFastOpen = getBoolean("network.ftcp-fastopen", tcpFastOpen);
+ }
+
}
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..6b9d788dfef2c51111e9f2129a04fce7754c51ba
--- /dev/null
+++ b/src/main/java/org/yatopiamc/yatopia/server/network/NetworkType.java
@@ -0,0 +1,110 @@
+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.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) {
+ 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;
+ }
+ }
+
+ if (Epoll.isAvailable()) {
+ return EPOLL;
+ }
+
+ if (KQueue.isAvailable()) {
+ return KQUEUE;
+ }
+
+ return NIO;
+ }
+
+ 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;
+ }
+ }
+}
Loading