Prevent exception when connecting using an older client

This commit is contained in:
themode 2021-01-06 03:16:46 +01:00
parent 2634105ad1
commit 7347c8df68
3 changed files with 35 additions and 14 deletions

View File

@ -51,27 +51,32 @@ public final class PacketProcessor {
} }
public void process(@NotNull ChannelHandlerContext channel, @NotNull InboundPacket packet) { public void process(@NotNull ChannelHandlerContext channel, @NotNull InboundPacket packet) {
final SocketChannel socketChannel = (SocketChannel) channel.channel();
// Create the netty player connection object if not existing // Create the netty player connection object if not existing
PlayerConnection playerConnection = connectionPlayerConnectionMap.computeIfAbsent( PlayerConnection playerConnection = connectionPlayerConnectionMap.computeIfAbsent(
channel, c -> new NettyPlayerConnection((SocketChannel) channel.channel()) channel, c -> new NettyPlayerConnection(socketChannel)
); );
// Prevent the client from sending packets when disconnected (kick) // Prevent the client from sending packets when disconnected (kick)
if (!playerConnection.isOnline()) { if (!playerConnection.isOnline() || !socketChannel.isActive()) {
playerConnection.disconnect(); playerConnection.disconnect();
return; return;
} }
if (MinecraftServer.getRateLimit() > 0) // Increment packet count (checked in PlayerConnection#update)
if (MinecraftServer.getRateLimit() > 0) {
playerConnection.getPacketCounter().incrementAndGet(); playerConnection.getPacketCounter().incrementAndGet();
}
final ConnectionState connectionState = playerConnection.getConnectionState(); final ConnectionState connectionState = playerConnection.getConnectionState();
BinaryReader binaryReader = new BinaryReader(packet.body); final int packetId = packet.getPacketId();
BinaryReader binaryReader = new BinaryReader(packet.getBody());
if (connectionState == ConnectionState.UNKNOWN) { if (connectionState == ConnectionState.UNKNOWN) {
// Should be handshake packet // Should be handshake packet
if (packet.packetId == 0) { if (packetId == 0) {
HandshakePacket handshakePacket = new HandshakePacket(); HandshakePacket handshakePacket = new HandshakePacket();
safeRead(playerConnection, handshakePacket, binaryReader); safeRead(playerConnection, handshakePacket, binaryReader);
handshakePacket.process(playerConnection); handshakePacket.process(playerConnection);
@ -82,17 +87,18 @@ public final class PacketProcessor {
switch (connectionState) { switch (connectionState) {
case PLAY: case PLAY:
final Player player = playerConnection.getPlayer(); final Player player = playerConnection.getPlayer();
ClientPlayPacket playPacket = (ClientPlayPacket) playPacketsHandler.getPacketInstance(packet.packetId); ClientPlayPacket playPacket = (ClientPlayPacket) playPacketsHandler.getPacketInstance(packetId);
safeRead(playerConnection, playPacket, binaryReader); safeRead(playerConnection, playPacket, binaryReader);
assert player != null;
player.addPacketToQueue(playPacket); player.addPacketToQueue(playPacket);
break; break;
case LOGIN: case LOGIN:
final ClientPreplayPacket loginPacket = (ClientPreplayPacket) loginPacketsHandler.getPacketInstance(packet.packetId); final ClientPreplayPacket loginPacket = (ClientPreplayPacket) loginPacketsHandler.getPacketInstance(packetId);
safeRead(playerConnection, loginPacket, binaryReader); safeRead(playerConnection, loginPacket, binaryReader);
loginPacket.process(playerConnection); loginPacket.process(playerConnection);
break; break;
case STATUS: case STATUS:
final ClientPreplayPacket statusPacket = (ClientPreplayPacket) statusPacketsHandler.getPacketInstance(packet.packetId); final ClientPreplayPacket statusPacket = (ClientPreplayPacket) statusPacketsHandler.getPacketInstance(packetId);
safeRead(playerConnection, statusPacket, binaryReader); safeRead(playerConnection, statusPacket, binaryReader);
statusPacket.process(playerConnection); statusPacket.process(playerConnection);
break; break;

View File

@ -1,5 +1,6 @@
package net.minestom.server.network.netty.channel; package net.minestom.server.network.netty.channel;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.SimpleChannelInboundHandler;
import net.minestom.server.MinecraftServer; import net.minestom.server.MinecraftServer;
@ -35,15 +36,21 @@ public class ClientChannel extends SimpleChannelInboundHandler<InboundPacket> {
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} finally { } finally {
final int availableBytes = packet.body.readableBytes(); // Check remaining
final ByteBuf body = packet.getBody();
final int packetId = packet.getPacketId();
final int availableBytes = body.readableBytes();
if (availableBytes > 0) { if (availableBytes > 0) {
final PlayerConnection playerConnection = packetProcessor.getPlayerConnection(ctx); final PlayerConnection playerConnection = packetProcessor.getPlayerConnection(ctx);
LOGGER.warn("WARNING: Packet 0x" + Integer.toHexString(packet.packetId) LOGGER.warn("WARNING: Packet 0x{} not fully read ({} bytes left), {}",
+ " not fully read (" + availableBytes + " bytes left), " + playerConnection); Integer.toHexString(packetId),
availableBytes,
playerConnection);
packet.body.skipBytes(availableBytes); body.skipBytes(availableBytes);
} }
} }
} }

View File

@ -5,12 +5,20 @@ import org.jetbrains.annotations.NotNull;
public class InboundPacket { public class InboundPacket {
public final int packetId; private final int packetId;
public final ByteBuf body; private final ByteBuf body;
public InboundPacket(int id, @NotNull ByteBuf body) { public InboundPacket(int id, @NotNull ByteBuf body) {
this.packetId = id; this.packetId = id;
this.body = body; this.body = body;
} }
public int getPacketId() {
return packetId;
}
@NotNull
public ByteBuf getBody() {
return body;
}
} }