diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java index c1f15cc19..d36846cc7 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java @@ -16,6 +16,7 @@ import com.velocitypowered.natives.encryption.VelocityCipher; import com.velocitypowered.natives.encryption.VelocityCipherFactory; import com.velocitypowered.natives.util.Natives; import com.velocitypowered.proxy.VelocityServer; +import com.velocitypowered.proxy.network.netty.DiscardHandler; import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.protocol.netty.MinecraftCipherDecoder; @@ -144,6 +145,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter { } } + ctx.pipeline().addBefore(MINECRAFT_DECODER, "discard", DiscardHandler.HANDLER); ctx.close(); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/netty/DiscardHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/network/netty/DiscardHandler.java new file mode 100644 index 000000000..80b34056e --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/netty/DiscardHandler.java @@ -0,0 +1,17 @@ +package com.velocitypowered.proxy.network.netty; + +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.util.ReferenceCountUtil; + +@Sharable +public class DiscardHandler extends ChannelInboundHandlerAdapter { + + public static final DiscardHandler HANDLER = new DiscardHandler(); + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + ReferenceCountUtil.release(msg); + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftDecoder.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftDecoder.java index 2cf96e84b..98e06f6ab 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftDecoder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftDecoder.java @@ -2,17 +2,26 @@ package com.velocitypowered.proxy.protocol.netty; import com.google.common.base.Preconditions; import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.network.Connections; import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.StateRegistry; +import com.velocitypowered.proxy.util.except.QuietException; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.codec.CorruptedFrameException; import io.netty.handler.codec.MessageToMessageDecoder; +import io.netty.util.ReferenceCountUtil; import java.util.List; public class MinecraftDecoder extends MessageToMessageDecoder { + private static final boolean DEBUG = Boolean.getBoolean("velocity.packet-decode-logging"); + private static final QuietException DECODE_FAILED = + new QuietException("A packet did not decode successfully (invalid data). If you are a " + + "developer, launch Velocity with -Dvelocity.packet-decode-logging=true to see more."); + private final ProtocolUtils.Direction direction; private StateRegistry state; private StateRegistry.PacketRegistry.ProtocolRegistry registry; @@ -46,17 +55,34 @@ public class MinecraftDecoder extends MessageToMessageDecoder { try { packet.decode(msg, direction, registry.version); } catch (Exception e) { - throw new CorruptedFrameException( - "Error decoding " + packet.getClass() + " " + getExtraConnectionDetail(packetId), e); + throw handleDecodeFailure(e, packet, packetId); } + if (msg.isReadable()) { - throw new CorruptedFrameException("Did not read full packet for " + packet.getClass() + " " - + getExtraConnectionDetail(packetId)); + throw handleNotReadEnough(packet, packetId); } out.add(packet); } } + private Exception handleNotReadEnough(MinecraftPacket packet, int packetId) { + if (DEBUG) { + return new CorruptedFrameException("Did not read full packet for " + packet.getClass() + " " + + getExtraConnectionDetail(packetId)); + } else { + return DECODE_FAILED; + } + } + + private Exception handleDecodeFailure(Exception cause, MinecraftPacket packet, int packetId) { + if (DEBUG) { + return new CorruptedFrameException( + "Error decoding " + packet.getClass() + " " + getExtraConnectionDetail(packetId), cause); + } else { + return DECODE_FAILED; + } + } + private String getExtraConnectionDetail(int packetId) { return "Direction " + direction + " Protocol " + registry.version + " State " + state + " ID " + Integer.toHexString(packetId);