From 2d75f3e529d7b71be3457edf2d67df793cdac722 Mon Sep 17 00:00:00 2001 From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> Date: Fri, 15 Aug 2025 02:50:29 +0800 Subject: [PATCH] Bump netty to 4.2.4 & Add io_uring, kqueue support (#449) * Bump netty to 4.2.3 * Upload config * Update config comments * Fix model detection * Switch to system properties * kqueue support * Bump to latest * Fix build --------- Co-authored-by: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com> --- leaf-server/build.gradle.kts.patch | 4 +- .../features/0281-Bump-netty-to-4.2.x.patch | 174 ++++++++++++++++++ .../features/0063-Bump-netty-to-4.2.x.patch | 25 +++ .../java/org/dreeam/leaf/NetworkIoModel.java | 44 +++++ 4 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 leaf-server/minecraft-patches/features/0281-Bump-netty-to-4.2.x.patch create mode 100644 leaf-server/paper-patches/features/0063-Bump-netty-to-4.2.x.patch create mode 100644 leaf-server/src/main/java/org/dreeam/leaf/NetworkIoModel.java diff --git a/leaf-server/build.gradle.kts.patch b/leaf-server/build.gradle.kts.patch index fffc3267..047d8d94 100644 --- a/leaf-server/build.gradle.kts.patch +++ b/leaf-server/build.gradle.kts.patch @@ -108,7 +108,7 @@ - implementation("io.netty:netty-codec-haproxy:4.1.118.Final") // Add support for proxy protocol - implementation("org.apache.logging.log4j:log4j-iostreams:2.24.1") + // Leaf start - Bump Dependencies -+ implementation("io.netty:netty-codec-haproxy:4.1.119.Final") // Add support for proxy protocol ++ implementation("io.netty:netty-codec-haproxy:4.2.4.Final") // Add support for proxy protocol // Leaf - Bump netty to 4.2.x + implementation("org.apache.logging.log4j:log4j-iostreams:2.24.3") + // Leaf end - Bump Dependencies implementation("org.ow2.asm:asm-commons:9.8") @@ -164,7 +164,7 @@ + implementation("me.lucko:spark-api:0.1-dev-f0b5206-SNAPSHOT") + implementation("me.lucko:spark-paper:1.10-dev-f0b5206-SNAPSHOT") + -+ implementation("io.netty:netty-all:4.1.119.Final") // Dreeam TODO - Update to 4.2.0 ++ implementation("io.netty:netty-all:4.2.4.Final") // Leaf - Bump netty to 4.2.x + // Leaf end - Bump Dependencies +} + diff --git a/leaf-server/minecraft-patches/features/0281-Bump-netty-to-4.2.x.patch b/leaf-server/minecraft-patches/features/0281-Bump-netty-to-4.2.x.patch new file mode 100644 index 00000000..0ba9b314 --- /dev/null +++ b/leaf-server/minecraft-patches/features/0281-Bump-netty-to-4.2.x.patch @@ -0,0 +1,174 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> +Date: Thu, 7 Aug 2025 00:22:50 +0800 +Subject: [PATCH] Bump netty to 4.2.x + + +diff --git a/net/minecraft/gametest/framework/GameTestServer.java b/net/minecraft/gametest/framework/GameTestServer.java +index 340d5487fa778277b9560250271c5143d80d9987..99543330da85ddecd91c954c8aa386c89a96c23f 100644 +--- a/net/minecraft/gametest/framework/GameTestServer.java ++++ b/net/minecraft/gametest/framework/GameTestServer.java +@@ -333,6 +333,18 @@ public class GameTestServer extends MinecraftServer { + return false; + } + ++ // Leaf start - Bump netty to 4.2.x ++ @Override ++ public boolean isIoUringEnabled() { ++ return false; ++ } ++ ++ @Override ++ public boolean isKqueueEnabled() { ++ return false; ++ } ++ // Leaf end - Bump netty to 4.2.x ++ + @Override + public boolean isCommandBlockEnabled() { + return true; +diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java +index 7849a905db35377da0931aa1c9b8770f30a51044..463f3d5334df16234c1794dd8c7bbea56cb87f70 100644 +--- a/net/minecraft/server/MinecraftServer.java ++++ b/net/minecraft/server/MinecraftServer.java +@@ -2064,6 +2064,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop SERVER_EVENT_GROUP = Suppliers.memoize( + () -> new NioEventLoopGroup(0, new ThreadFactoryBuilder().setNameFormat("Netty Server IO #%d").setDaemon(true).setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(LOGGER)).build()) // Paper + ); + public static final Supplier SERVER_EPOLL_EVENT_GROUP = Suppliers.memoize( + () -> new EpollEventLoopGroup(0, new ThreadFactoryBuilder().setNameFormat("Netty Epoll Server IO #%d").setDaemon(true).setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(LOGGER)).build()) // Paper + ); ++ */ ++ public static final Supplier NIO_IO_HANDLE_FACTORY = io.netty.channel.nio.NioIoHandler::newFactory; ++ public static final Supplier EPOLL_IO_HANDLE_FACTORY = io.netty.channel.epoll.EpollIoHandler::newFactory; ++ public static final Supplier IO_URING_IO_HANDLE_FACTORY = io.netty.channel.uring.IoUringIoHandler::newFactory; ++ public static final Supplier KQUEUE_IO_HANDLE_FACTORY = io.netty.channel.kqueue.KQueueIoHandler::newFactory; ++ // Leaf end - Bump netty to 4.2.x + final MinecraftServer server; + public volatile boolean running; + private final List channels = Collections.synchronizedList(Lists.newArrayList()); +@@ -87,7 +95,29 @@ public class ServerConnectionListener { + synchronized (this.channels) { + Class clazz; // Paper - Unix domain socket support + EventLoopGroup eventLoopGroup; +- if (Epoll.isAvailable() && this.server.isEpollEnabled()) { ++ // Leaf start - Bump netty to 4.2.x ++ if (io.netty.channel.uring.IoUring.isAvailable() && this.server.isIoUringEnabled()) { ++ // Paper start - Unix domain socket support ++ if (address instanceof io.netty.channel.unix.DomainSocketAddress) { ++ clazz = io.netty.channel.uring.IoUringServerDomainSocketChannel.class; ++ } else { ++ clazz = io.netty.channel.uring.IoUringServerSocketChannel.class; ++ } ++ // Paper end - Unix domain socket supp ++ eventLoopGroup = createEventLoopGroup("IoUring", IO_URING_IO_HANDLE_FACTORY); ++ LOGGER.info("Using io_uring channel type"); ++ } else if (io.netty.channel.kqueue.KQueue.isAvailable() && this.server.isKqueueEnabled()) { ++ // Paper start - Unix domain socket support ++ if (address instanceof io.netty.channel.unix.DomainSocketAddress) { ++ clazz = io.netty.channel.kqueue.KQueueServerDomainSocketChannel.class; ++ } else { ++ clazz = io.netty.channel.kqueue.KQueueServerSocketChannel.class; ++ } ++ // Paper end - Unix domain socket support ++ eventLoopGroup = createEventLoopGroup("Kqueue", KQUEUE_IO_HANDLE_FACTORY); ++ LOGGER.info("Using kqueue channel type"); ++ } else if (Epoll.isAvailable() && this.server.isEpollEnabled()) { ++ // Leaf end - Bump netty to 4.2.x + // Paper start - Unix domain socket support + if (address instanceof io.netty.channel.unix.DomainSocketAddress) { + clazz = io.netty.channel.epoll.EpollServerDomainSocketChannel.class; +@@ -95,12 +125,12 @@ public class ServerConnectionListener { + clazz = EpollServerSocketChannel.class; + } + // Paper end - Unix domain socket support +- eventLoopGroup = SERVER_EPOLL_EVENT_GROUP.get(); ++ eventLoopGroup = createEventLoopGroup("Epoll", EPOLL_IO_HANDLE_FACTORY); // Leaf - Bump netty to 4.2.x + LOGGER.info("Using epoll channel type"); + } else { + clazz = NioServerSocketChannel.class; +- eventLoopGroup = SERVER_EVENT_GROUP.get(); +- LOGGER.info("Using default channel type"); ++ eventLoopGroup = createEventLoopGroup("Nio", NIO_IO_HANDLE_FACTORY); // Leaf - Bump netty to 4.2.x ++ LOGGER.info("Using default nio channel type"); // Leaf - Bump netty to 4.2.x + } + + // Paper start - Warn people with console access that HAProxy is in use. +@@ -195,6 +225,19 @@ public class ServerConnectionListener { + } + // CraftBukkit end + ++ // Leaf start - Bump netty to 4.2.x ++ public EventLoopGroup createEventLoopGroup(final String name, final Supplier ioHandlerFactorySupplier) { ++ return new io.netty.channel.MultiThreadIoEventLoopGroup( ++ 0, ++ new ThreadFactoryBuilder().setNameFormat("Netty " + name + " Server IO #%d") ++ .setDaemon(true) ++ .setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(LOGGER)) ++ .build(), ++ ioHandlerFactorySupplier.get() ++ ); ++ } ++ // Leaf end - Bump netty to 4.2.x ++ + public SocketAddress startMemoryChannel() { + ChannelFuture channelFuture; + synchronized (this.channels) { +@@ -215,7 +258,7 @@ public class ServerConnectionListener { + } + } + ) +- .group(SERVER_EVENT_GROUP.get()) ++ //.group(SERVER_EVENT_GROUP.get()) // Leaf - Bump netty to 4.2.x - not used, comment + .localAddress(LocalAddress.ANY) + .bind() + .syncUninterruptibly(); diff --git a/leaf-server/paper-patches/features/0063-Bump-netty-to-4.2.x.patch b/leaf-server/paper-patches/features/0063-Bump-netty-to-4.2.x.patch new file mode 100644 index 00000000..76d99453 --- /dev/null +++ b/leaf-server/paper-patches/features/0063-Bump-netty-to-4.2.x.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> +Date: Thu, 7 Aug 2025 00:22:50 +0800 +Subject: [PATCH] Bump netty to 4.2.x + + +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 748bd9650da4a209743b7a5dde584b2e19c5a578..3e972dc2160f953daaa727c2305ec71eed7981a5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -21,6 +21,14 @@ public class Main { + // Paper start - Reset loggers after shutdown + static { + System.setProperty("java.util.logging.manager", "io.papermc.paper.log.CustomLogManager"); ++ ++ // Leaf start - Bump netty to 4.2.x ++ // Fallback to original pooled allocator if no explicitly define adaptive allocator ++ // To follow https://github.com/netty/netty/wiki/Netty-4.2-Migration-Guide ++ if (System.getProperty("io.netty.allocator.type") == null) { ++ System.setProperty("io.netty.allocator.type", "pooled"); ++ } ++ // Leaf end - Bump netty to 4.2.x + } + // Paper end - Reset loggers after shutdown + diff --git a/leaf-server/src/main/java/org/dreeam/leaf/NetworkIoModel.java b/leaf-server/src/main/java/org/dreeam/leaf/NetworkIoModel.java new file mode 100644 index 00000000..2ae568ef --- /dev/null +++ b/leaf-server/src/main/java/org/dreeam/leaf/NetworkIoModel.java @@ -0,0 +1,44 @@ +// Leaf - Bump netty to 4.2.x + +package org.dreeam.leaf; + +import java.util.Locale; + +public enum NetworkIoModel { + + IO_URING("io_uring"), + KQUEUE("kqueue"), + EPOLL("epoll"), + NIO("nio"); + + private final String name; + + NetworkIoModel(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + + public static NetworkIoModel fromName(String name) { + if (name == null) return EPOLL; + return switch (name.toLowerCase(Locale.ROOT)) { + case "io_uring" -> IO_URING; + case "kqueue" -> KQUEUE; + case "epoll" -> EPOLL; + default -> NIO; + }; + } + + public static NetworkIoModel fromProperty() { + final String name = System.getProperty("Leaf.native-transport-type"); + if (name == null) return EPOLL; + return switch (name.toLowerCase(Locale.ROOT)) { + case "io_uring" -> IO_URING; + case "kqueue" -> KQUEUE; + case "epoll" -> EPOLL; + default -> NIO; + }; + } +}