Skip to content

Commit

Permalink
Set autoread to false and clear tcp read buf, ensure only do it once
Browse files Browse the repository at this point in the history
  • Loading branch information
Outfluencer committed Feb 17, 2025
1 parent b0ac7b9 commit 51165fe
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,26 @@
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<Object> out) throws Exception
{
// If we decode an invalid packet and an exception is thrown (thus triggering a close of the connection),
// 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;
Expand Down
34 changes: 26 additions & 8 deletions proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 );
}
}

Expand Down
8 changes: 0 additions & 8 deletions proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down

0 comments on commit 51165fe

Please sign in to comment.