Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.github.retrooper.packetevents.impl.netty.util;

import com.github.retrooper.packetevents.protocol.ConnectionState;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import com.github.retrooper.packetevents.wrapper.configuration.server.WrapperConfigServerDisconnect;
import com.github.retrooper.packetevents.wrapper.login.server.WrapperLoginServerDisconnect;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDisconnect;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

@NullMarked
@ApiStatus.Internal
public final class WrapperUtil {
Comment thread
ShadowOfHeaven-Me marked this conversation as resolved.

public static @Nullable PacketWrapper<?> createDisconnectWrapper(@NonNull ConnectionState state, @NonNull Component component) {
switch (state) {
case HANDSHAKING:
case STATUS:
return null;
case LOGIN:
return new WrapperLoginServerDisconnect(component);
case PLAY:
return new WrapperPlayServerDisconnect(component);
case CONFIGURATION:
return new WrapperConfigServerDisconnect(component);
default:
throw new AssertionError();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,9 @@ public void channelInactive(@NotNull ChannelHandlerContext ctx) throws Exception
ServerConnectionInitializer.destroyChannel(ctx.channel());
super.channelInactive(ctx);
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
super.exceptionCaught(ctx, cause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,23 @@

import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.exception.PacketProcessException;
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.protocol.ConnectionState;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.util.EventCreationUtil;
import com.github.retrooper.packetevents.util.ExceptionUtil;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import com.velocitypowered.api.proxy.Player;
import io.github.retrooper.packetevents.impl.netty.util.WrapperUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import net.kyori.adventure.text.Component;

import java.net.InetSocketAddress;

@ChannelHandler.Sharable
public class PacketEventsEncoder extends MessageToByteEncoder<ByteBuf> {
Expand Down Expand Up @@ -74,9 +83,41 @@ protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throw
}
}

//true if handled, false if not our exception
static boolean onExceptionCaught(Channel channel, User user, Throwable cause) {
boolean didWeCauseThis = ExceptionUtil.isException(cause, PacketProcessException.class);
if (didWeCauseThis) {
boolean loggable = (user != null && user.getDecoderState() != ConnectionState.HANDSHAKING);

if (loggable) {
if (PacketEvents.getAPI().getSettings().isFullStackTraceEnabled()) {
String name = user.getName();

String id = name != null ? name : ((InetSocketAddress) channel.remoteAddress()).getAddress().getHostAddress();
PacketEvents.getAPI().getLogManager().severe("Disconnecting " + id + " due to an invalid packet!", cause);
} else {
PacketEvents.getAPI().getLogManager().warn(cause.getMessage());
}
}

if (PacketEvents.getAPI().getSettings().isKickOnPacketExceptionEnabled()) {
if (user != null) {
PacketWrapper<?> wrapper = WrapperUtil.createDisconnectWrapper(user.getEncoderState(), Component.text("Invalid packet"));

if (wrapper != null) {
user.sendPacket(wrapper);
}
}
channel.close();
}
return true;
}
Comment thread
ShadowOfHeaven-Me marked this conversation as resolved.
return false;
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
super.exceptionCaught(ctx, cause);
if (!onExceptionCaught(ctx.channel(), this.user, cause))
super.exceptionCaught(ctx, cause);
}
}

Loading