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 7 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
1 change: 1 addition & 0 deletions PATCHES.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ This is an overview over all patches that are currently used.
| api | Modify POM | YatopiaMC | |
| server | Modify POM | YatopiaMC | |
| server | Modify default configs | tr7zw | |
| server | New Network System | Hugo Planque | |
| server | Nuke streams off BlockPosition | Ivan Pekov | |
| server | Nuke streams off SectionPosition | Ivan Pekov | |
| server | Optimise portals | Ivan Pekov | |
Expand Down
297 changes: 297 additions & 0 deletions patches/server/0066-New-Network-System.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
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


diff --git a/pom.xml b/pom.xml
index cd681eb181571543b63108f33d1d3f129c035e84..d28bd6ddbe3e61da90c49151eb5f17e0cda53c10 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,9 +51,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/ServerConnection.java b/src/main/java/net/minecraft/server/ServerConnection.java
index 0668d383db1f3a81d1053954d72678c7ac5aecec..788bcaa3a645969ab9f036adc58d800c0b9ebd72 100644
--- a/src/main/java/net/minecraft/server/ServerConnection.java
+++ b/src/main/java/net/minecraft/server/ServerConnection.java
@@ -26,16 +26,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.util.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 +56,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(LOGGER, minecraftserver);
+ this.boss = networkType.createEventLoopGroup(NetworkType.Type.BOSS);
+ this.worker = networkType.createEventLoopGroup(NetworkType.Type.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,13 +91,17 @@ 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.");
+
+ this.listeningChannels.add((((new ServerBootstrap()).channelFactory(networkType.getServerSocketChannelFactory())).childHandler(new ChannelInitializer<Channel>() {
protected void initChannel(Channel channel) throws Exception {
try {
channel.config().setOption(ChannelOption.TCP_NODELAY, true);
@@ -97,7 +119,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 00c600d74ba84cb564b9b22f53f279a93839d71f..390715d5495142c214562d53612cf71dc9fc1d72 100644
--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
+++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
@@ -297,4 +297,9 @@ public class YatopiaConfig {
private static void tickEnchantingTables() {
shouldTickEnchantingTables = getBoolean("settings.tick.enchanting-tables", shouldTickEnchantingTables);
}
+
+ public static boolean ioUringBeta = false;
+ private static void newNetworkSystem() {
+ ioUringBeta = getBoolean("network.io-uring", ioUringBeta);
+ }
}
diff --git a/src/main/java/org/yatopiamc/yatopia/server/util/NetworkType.java b/src/main/java/org/yatopiamc/yatopia/server/util/NetworkType.java
new file mode 100644
index 0000000000000000000000000000000000000000..bca118400f67d81469bddbcaeb49a5e1f8e36239
--- /dev/null
+++ b/src/main/java/org/yatopiamc/yatopia/server/util/NetworkType.java
@@ -0,0 +1,164 @@
+package org.yatopiamc.yatopia.server.util;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import io.netty.channel.ChannelFactory;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.epoll.Epoll;
+import io.netty.channel.epoll.EpollDatagramChannel;
+import io.netty.channel.epoll.EpollEventLoopGroup;
+import io.netty.channel.epoll.EpollServerSocketChannel;
+import io.netty.channel.epoll.EpollSocketChannel;
+import io.netty.channel.kqueue.KQueue;
+import io.netty.channel.kqueue.KQueueDatagramChannel;
+import io.netty.channel.kqueue.KQueueEventLoopGroup;
+import io.netty.channel.kqueue.KQueueServerSocketChannel;
+import io.netty.channel.kqueue.KQueueSocketChannel;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.DatagramChannel;
+import io.netty.channel.socket.ServerSocketChannel;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioDatagramChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.incubator.channel.uring.IOUring;
+import io.netty.incubator.channel.uring.IOUringDatagramChannel;
+import io.netty.incubator.channel.uring.IOUringEventLoopGroup;
+import io.netty.incubator.channel.uring.IOUringServerSocketChannel;
+import io.netty.incubator.channel.uring.IOUringSocketChannel;
+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;
+
+/**
+ * This class is based on astei work on
+ * https://github.com/VelocityPowered/Velocity/blob/dev/1.1.0/proxy/src/main/java/com/velocitypowered/proxy/network/TransportType.java
+ */
+public enum NetworkType {
+ NIO("NIO", NioServerSocketChannel.class, NioServerSocketChannel::new, NioSocketChannel.class, NioSocketChannel::new, NioDatagramChannel.class,
+ NioDatagramChannel::new,
+ (name, type) -> new NioEventLoopGroup(8, createThreadFactory(name, type))),
+
+ EPOLL("Epoll", EpollServerSocketChannel.class, EpollServerSocketChannel::new, EpollSocketChannel.class, EpollSocketChannel::new,
+ EpollDatagramChannel.class, EpollDatagramChannel::new,
+ (name, type) -> new EpollEventLoopGroup(8, createThreadFactory(name, type))),
+
+ IOURING("IOUring", IOUringServerSocketChannel.class, IOUringServerSocketChannel::new, IOUringSocketChannel.class, IOUringSocketChannel::new,
+ IOUringDatagramChannel.class, IOUringDatagramChannel::new,
+ (name, type) -> new IOUringEventLoopGroup(8, createThreadFactory(name, type))),
+
+ KQUEUE("Kqueue", KQueueServerSocketChannel.class, KQueueServerSocketChannel::new, KQueueSocketChannel.class, KQueueSocketChannel::new,
+ KQueueDatagramChannel.class, KQueueDatagramChannel::new,
+ (name, type) -> new KQueueEventLoopGroup(8, createThreadFactory(name, type)));
+
+ public final String name;
+ public final Class<? extends ServerSocketChannel> serverSocketChannelClass;
+ public final ChannelFactory<? extends ServerSocketChannel> serverSocketChannelFactory;
+ public final Class<? extends SocketChannel> socketChannelClass;
+ public final ChannelFactory<? extends SocketChannel> socketChannelFactory;
+ public final Class<? extends DatagramChannel> datagramChannelClass;
+ public final ChannelFactory<? extends DatagramChannel> channelFactory;
+ public final BiFunction<String, Type, EventLoopGroup> eventLoopGroupFactory;
+
+ NetworkType(final String name,
+ final Class<? extends ServerSocketChannel> serverSocketChannelClass,
+ final ChannelFactory<? extends ServerSocketChannel> serverSocketChannelFactory,
+ final Class<? extends SocketChannel> socketChannelClass,
+ final ChannelFactory<? extends SocketChannel> socketChannelFactory,
+ final Class<? extends DatagramChannel> datagramChannelClass,
+ final ChannelFactory<? extends DatagramChannel> channelFactory,
+ final BiFunction<String, Type, EventLoopGroup> eventLoopGroupFactory) {
+ this.name = name;
+ this.serverSocketChannelClass = serverSocketChannelClass;
+ this.serverSocketChannelFactory = serverSocketChannelFactory;
+ this.socketChannelClass = socketChannelClass;
+ this.socketChannelFactory = socketChannelFactory;
+ this.datagramChannelClass = datagramChannelClass;
+ this.channelFactory = channelFactory;
+ 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 Type type) {
+ return this.eventLoopGroupFactory.apply(this.name, type);
+ }
+
+ private static ThreadFactory createThreadFactory(final String name, final Type type) {
+ return new ThreadFactoryBuilder()
+ .setNameFormat("Netty " + name + " " + type.toString() + " #%1$d")
+ .setDaemon(true)
+ .build();
+ }
+
+ public static NetworkType bestType(Logger logger, MinecraftServer minecraftServer) {
+ if (!minecraftServer.l()) {
+ 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
+ if (!SpigotConfig.bungee && YatopiaConfig.ioUringBeta) {
+ logger.log(Level.ERROR, "Attempting to use enhanced IOUringEventLoop");
+ if (IOUring.isAvailable()) {
+ return IOURING;
+ }
+ logger.log(Level.ERROR, "IOUring is not working, falling back to Epoll: {}", exceptionMessage(IOUring.unavailabilityCause()));
+ }
+
+ logger.info("Attempting to use enhanced EpollEventLoop");
+ if (Epoll.isAvailable()) {
+ return EPOLL;
+ }
+ logger.log(Level.ERROR, "Epoll is not working, falling back to KQueue: {}", exceptionMessage(Epoll.unavailabilityCause()));
+
+ logger.info("Attempting to use enhanced KQueueEventLoop");
+ if (KQueue.isAvailable()) {
+ return KQUEUE;
+ }
+ logger.log(Level.ERROR, "KQueue is not working, falling back to NIO: {}", 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 Type {
+ BOSS("Boss"),
+ WORKER("Worker");
+
+ private final String name;
+
+ Type(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return this.name;
+ }
+ }
+}