From f00933fd613a42f3148ebc5eabc322e3ab1bf874 Mon Sep 17 00:00:00 2001 From: RaphiMC <50594595+RaphiMC@users.noreply.github.com> Date: Mon, 1 Dec 2025 22:58:10 +0100 Subject: [PATCH] Cleaned up packet capture code (Follow up to #2) --- .../client/RakClientFirstPacketHandler.java | 22 +++++ .../RakClientNetworkSettingsHandler.java | 80 ------------------- .../RakClientOfflineHandlerCompatible.java | 9 +-- ...kClientOnlineInitialHandlerCompatible.java | 10 +-- 4 files changed, 31 insertions(+), 90 deletions(-) create mode 100644 transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientFirstPacketHandler.java delete mode 100644 transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientNetworkSettingsHandler.java diff --git a/transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientFirstPacketHandler.java b/transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientFirstPacketHandler.java new file mode 100644 index 0000000..9f37914 --- /dev/null +++ b/transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientFirstPacketHandler.java @@ -0,0 +1,22 @@ +package org.cloudburstmc.netty.handler.codec.raknet.client; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelOutboundHandlerAdapter; +import io.netty.channel.ChannelPromise; +import io.netty.util.concurrent.Promise; + +public class RakClientFirstPacketHandler extends ChannelOutboundHandlerAdapter { + public static final String NAME = "rak-client-first-packet-handler"; + + private final Promise packetPromise; + + public RakClientFirstPacketHandler(Promise packetPromise) { + this.packetPromise = packetPromise; + } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + ctx.channel().pipeline().remove(RakClientFirstPacketHandler.NAME); + this.packetPromise.setSuccess(msg); + } +} diff --git a/transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientNetworkSettingsHandler.java b/transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientNetworkSettingsHandler.java deleted file mode 100644 index 3a8755e..0000000 --- a/transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientNetworkSettingsHandler.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.cloudburstmc.netty.handler.codec.raknet.client; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelOutboundHandlerAdapter; -import io.netty.channel.ChannelPromise; -import io.netty.util.concurrent.Promise; -import org.cloudburstmc.netty.channel.raknet.RakChannel; -import org.cloudburstmc.netty.channel.raknet.RakPriority; -import org.cloudburstmc.netty.channel.raknet.RakReliability; -import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption; -import org.cloudburstmc.netty.channel.raknet.packet.RakMessage; - -import static org.cloudburstmc.netty.channel.raknet.RakConstants.ID_GAME_PACKET; - -public class RakClientNetworkSettingsHandler extends ChannelOutboundHandlerAdapter { - public static final String NAME = "rak-client-network-settings-handler"; - - private final RakChannel channel; - private final Promise networkSettingsPacketPromise; - - public RakClientNetworkSettingsHandler(RakChannel channel, Promise networkSettingsPacketPromise) { - this.channel = channel; - this.networkSettingsPacketPromise = networkSettingsPacketPromise; - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - ctx.channel().pipeline().remove(RakClientNetworkSettingsHandler.NAME); - - RakMessage packet; - - if (!(msg instanceof RakMessage)) { - if (msg instanceof ByteBuf) { - packet = new RakMessage((ByteBuf) msg, RakReliability.RELIABLE_ORDERED, RakPriority.NORMAL); - } else { - throw new IllegalStateException("First packet was not an instance of RakMessage or ByteBuf: class " + msg.getClass().getName()); - } - } else { - packet = (RakMessage) msg; - } - - ByteBuf content = packet.content(); - - if (content.capacity() < 4) { - throw new IllegalStateException("First packet was not a RequestNetworkSettings packet: Content less than 4 bytes"); - } - - if (content.getByte(0) != (byte) ID_GAME_PACKET) { - throw new IllegalStateException("First packet was not a RequestNetworkSettings packet: Expected RakNet game packet ID (" + ID_GAME_PACKET + "), but got " + content.getByte(0)); - } - - int rakVersion = this.channel.config().getOption(RakChannelOption.RAK_PROTOCOL_VERSION); - - switch (rakVersion) { - case 11: - case 10: - case 9: - if (content.getByte(1) != (byte) 0x06) break; - if (content.getByte(2) != (byte) 0xc1) break; - if ((content.getByte(3) & (byte) 0b10000111) != (byte) 0b00000001) break; - this.networkSettingsPacketPromise.setSuccess(packet); - return; - case 8: - if (content.getByte(1) != (byte) 0x07) break; - if (content.getByte(2) != (byte) 0xc1) break; - this.networkSettingsPacketPromise.setSuccess(packet); - return; - case 7: - if (content.getByte(1) != (byte) 0x05) break; - if (content.getByte(2) != (byte) 0xc1) break; - this.networkSettingsPacketPromise.setSuccess(packet); - return; - default: - throw new UnsupportedOperationException("Unsupported protocol version: " + rakVersion); - } - - throw new IllegalStateException("First packet was not a RequestNetworkSettings packet: Invalid Bedrock packet ID"); - } -} diff --git a/transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientOfflineHandlerCompatible.java b/transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientOfflineHandlerCompatible.java index 0ef64d6..cc1a4d8 100644 --- a/transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientOfflineHandlerCompatible.java +++ b/transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientOfflineHandlerCompatible.java @@ -8,7 +8,6 @@ import org.cloudburstmc.netty.channel.raknet.RakChannel; import org.cloudburstmc.netty.channel.raknet.RakOfflineState; import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption; -import org.cloudburstmc.netty.channel.raknet.packet.RakMessage; import org.cloudburstmc.netty.handler.codec.raknet.common.*; import org.cloudburstmc.netty.util.RakUtils; @@ -31,18 +30,18 @@ void onRetryAttempt(Channel channel) { @Override void onSuccess(ChannelHandlerContext ctx) { RakSessionCodec sessionCodec = new RakSessionCodecCompatible(this.rakChannel()); - Promise networkSettingsPacketPromise = ctx.executor().newPromise(); + Promise packetPromise = ctx.executor().newPromise(); ctx.pipeline().addAfter(NAME, RakDatagramCodec.NAME, new RakDatagramCodec()); ctx.pipeline().addAfter(RakDatagramCodec.NAME, RakAcknowledgeHandler.NAME, new RakAcknowledgeHandler(sessionCodec)); ctx.pipeline().addAfter(RakAcknowledgeHandler.NAME, RakSessionCodec.NAME, sessionCodec); - // Ensure new incoming connection batches with request network settings game packet - ctx.pipeline().addAfter(RakSessionCodec.NAME, RakClientNetworkSettingsHandler.NAME, new RakClientNetworkSettingsHandler(this.rakChannel(), networkSettingsPacketPromise)); + // Ensure new incoming connection batches with first game packet (request network settings) + ctx.pipeline().addAfter(RakSessionCodec.NAME, RakClientFirstPacketHandler.NAME, new RakClientFirstPacketHandler(packetPromise)); ctx.pipeline().addAfter(RakSessionCodec.NAME, ConnectedPingHandler.NAME, new ConnectedPingHandler()); ctx.pipeline().addAfter(ConnectedPingHandler.NAME, ConnectedPongHandler.NAME, new ConnectedPongHandler(sessionCodec)); ctx.pipeline().addAfter(ConnectedPongHandler.NAME, DisconnectNotificationHandler.NAME, DisconnectNotificationHandler.INSTANCE); // Replicate server behavior, and transform unhandled encapsulated packets to rakMessage ctx.pipeline().addAfter(DisconnectNotificationHandler.NAME, EncapsulatedToMessageHandler.NAME, EncapsulatedToMessageHandler.INSTANCE); - ctx.pipeline().addAfter(DisconnectNotificationHandler.NAME, RakClientOnlineInitialHandlerCompatible.NAME, new RakClientOnlineInitialHandlerCompatible(this.rakChannel(), this.successPromise(), networkSettingsPacketPromise)); + ctx.pipeline().addAfter(DisconnectNotificationHandler.NAME, RakClientOnlineInitialHandlerCompatible.NAME, new RakClientOnlineInitialHandlerCompatible(this.rakChannel(), this.successPromise(), packetPromise)); } @Override diff --git a/transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientOnlineInitialHandlerCompatible.java b/transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientOnlineInitialHandlerCompatible.java index 4a831a8..1ba793f 100644 --- a/transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientOnlineInitialHandlerCompatible.java +++ b/transport-raknet/src/main/java/org/cloudburstmc/netty/handler/codec/raknet/client/RakClientOnlineInitialHandlerCompatible.java @@ -16,20 +16,20 @@ public class RakClientOnlineInitialHandlerCompatible extends RakClientOnlineInitialHandler { public static final String NAME = "rak-client-online-initial-handler"; - private final Promise networkSettingsPacketPromise; + private final Promise packetPromise; private long pingTime = 0; - public RakClientOnlineInitialHandlerCompatible(RakChannel rakChannel, ChannelPromise successPromise, Promise networkSettingsPacketPromise) { + public RakClientOnlineInitialHandlerCompatible(RakChannel rakChannel, ChannelPromise successPromise, Promise packetPromise) { super(rakChannel, successPromise); - this.networkSettingsPacketPromise = networkSettingsPacketPromise; + this.packetPromise = packetPromise; } @Override void onSuccess(ChannelHandlerContext ctx) { super.onSuccess(ctx); - // Wait for the RequestNetworkSettings packet before sending the final batch - this.networkSettingsPacketPromise.addListener(future -> { + // Wait for the first game packet (request network settings) before sending the final batch + this.packetPromise.addListener(future -> { ByteBuf incomingBuffer = ctx.alloc().ioBuffer(); this.writeIncomingConnection(ctx, incomingBuffer, pingTime); ctx.write(new RakMessage(incomingBuffer, RakReliability.RELIABLE_ORDERED, RakPriority.NORMAL));