From 51165fe4b5385c5b6710710b83548ae96e8cc153 Mon Sep 17 00:00:00 2001 From: Outfluencer Date: Mon, 17 Feb 2025 18:54:36 +0100 Subject: [PATCH] Set autoread to false and clear tcp read buf, ensure only do it once --- .../bungee/protocol/Varint21FrameDecoder.java | 8 ++++- .../net/md_5/bungee/netty/ChannelWrapper.java | 34 ++++++++++++++----- .../net/md_5/bungee/netty/HandlerBoss.java | 8 ----- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java b/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java index 277e70e8a2..e318a28e0f 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java @@ -6,12 +6,18 @@ import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.CorruptedFrameException; import java.util.List; +import lombok.Setter; public class Varint21FrameDecoder extends ByteToMessageDecoder { private static boolean DIRECT_WARNING; + // discard will be set to true before we close a connection to ensure + // that no packets will be handled anymore + @Setter + private boolean discard; + @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { @@ -19,7 +25,7 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) t // the Netty ByteToMessageDecoder will continue to frame more packets and potentially call fireChannelRead() // on them, likely with more invalid packets. Therefore, check if the connection is no longer active and if so // sliently discard the packet. - if ( !ctx.channel().isActive() ) + if ( !ctx.channel().isActive() || discard ) { in.skipBytes( in.readableBytes() ); return; diff --git a/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java b/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java index fda4f54eb8..05111ec245 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java @@ -18,6 +18,7 @@ import net.md_5.bungee.protocol.MinecraftEncoder; import net.md_5.bungee.protocol.PacketWrapper; import net.md_5.bungee.protocol.Protocol; +import net.md_5.bungee.protocol.Varint21FrameDecoder; import net.md_5.bungee.protocol.packet.Kick; public class ChannelWrapper @@ -130,6 +131,13 @@ public void close(Object packet) { if ( !closed ) { + // do not do it twice + if ( !closing ) + { + // clear tcp read buffer + discardInbound(); + } + closed = closing = true; // disable auto read so the pipeline doesn't read more traffic @@ -152,21 +160,31 @@ public void delayedClose(final Kick kick) { closing = true; + // clear tcp read buffer + discardInbound(); + // disable auto read so the pipeline doesn't read more traffic ch.config().setAutoRead( false ); // Minecraft client can take some time to switch protocols. // Sending the wrong disconnect packet whilst a protocol switch is in progress will crash it. // Delay 250ms to ensure that the protocol switch (if any) has definitely taken place. - ch.eventLoop().schedule( new Runnable() - { + ch.eventLoop().schedule( () -> close( kick ), 250, TimeUnit.MILLISECONDS ); + } + } - @Override - public void run() - { - close( kick ); - } - }, 250, TimeUnit.MILLISECONDS ); + /** + * Disable auto read so the pipeline doesn't read more traffic + * Also discard all inbound traffic to free the tcp read buffer + * This clears the tcp read buffer + */ + private void discardInbound() + { + ch.config().setAutoRead( false ); + Varint21FrameDecoder frameDecoder = ch.pipeline().get( Varint21FrameDecoder.class ); + if ( frameDecoder != null ) + { + frameDecoder.setDiscard( true ); } } diff --git a/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java b/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java index 634968968e..a73a29c77d 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java @@ -128,14 +128,6 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { handler, limiter.getCounter(), limiter.getDataCounter() } ); - - // somehow sometimes if you spam big packets fast enough the channel will not be closed immediately - // it seems that this only happens on linux, the PacketLimiter will trigger a kick multiple times - // but the connection will still be active - if ( channel.getHandle().isActive() ) - { - ctx.close(); - } return; }