From e6ecfcdfeee4ac46bc822970feaee79d3de04414 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Sun, 3 Aug 2025 21:32:10 +0200 Subject: [PATCH] Handle empty packid's in resource pack response packet --- .../java/org/geysermc/geyser/GeyserImpl.java | 6 +++- .../geysermc/geyser/event/GeyserEventBus.java | 9 +++++ .../geyser/network/UpstreamPacketHandler.java | 33 +++++++++++++------ 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 2267a3e92..27a039a96 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -168,7 +168,7 @@ public class GeyserImpl implements GeyserApi, EventRegistrar { private final PlatformType platformType; private final GeyserBootstrap bootstrap; - private final EventBus eventBus; + private final GeyserEventBus eventBus; private final GeyserExtensionManager extensionManager; private Metrics metrics; @@ -754,6 +754,10 @@ public class GeyserImpl implements GeyserApi, EventRegistrar { return this.eventBus; } + public GeyserEventBus geyserEventBus() { + return this.eventBus; + } + @NonNull public RemoteServer defaultRemoteServer() { return getConfig().getRemote(); diff --git a/core/src/main/java/org/geysermc/geyser/event/GeyserEventBus.java b/core/src/main/java/org/geysermc/geyser/event/GeyserEventBus.java index d8657b612..ddebf02e4 100644 --- a/core/src/main/java/org/geysermc/geyser/event/GeyserEventBus.java +++ b/core/src/main/java/org/geysermc/geyser/event/GeyserEventBus.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.event; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.event.Event; +import org.geysermc.event.FireResult; import org.geysermc.event.PostOrder; import org.geysermc.event.bus.impl.OwnedEventBusImpl; import org.geysermc.event.subscribe.OwnedSubscriber; @@ -34,6 +35,7 @@ import org.geysermc.event.subscribe.Subscribe; import org.geysermc.geyser.api.event.EventBus; import org.geysermc.geyser.api.event.EventRegistrar; import org.geysermc.geyser.api.event.EventSubscriber; +import org.geysermc.geyser.session.GeyserSession; import java.util.Set; import java.util.function.BiConsumer; @@ -68,4 +70,11 @@ public final class GeyserEventBus extends OwnedEventBusImpl Set> subscribers(@NonNull Class eventClass) { return castGenericSet(super.subscribers(eventClass)); } + + public void fireEventElseKick(@NonNull Event event, GeyserSession session) { + FireResult result = this.fire(event); + if (!result.success()) { + session.disconnect("Internal server error occurred! Please contact a server administrator."); + } + } } diff --git a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index 3f66a3af9..3ad5d65f6 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -93,12 +93,10 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { private boolean finishedResourcePackSending = false; private final Deque packsToSend = new ArrayDeque<>(); private final CompressionStrategy compressionStrategy; - // Avoid overloading consoles when downloading larger resource packs private static final int PACKET_SEND_DELAY = 4 * 50; private final Queue chunkRequestQueue = new ConcurrentLinkedQueue<>(); private boolean currentlySendingChunks = false; - private SessionLoadResourcePacksEventImpl resourcePackLoadEvent; public UpstreamPacketHandler(GeyserImpl geyser, GeyserSession session) { @@ -196,8 +194,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { } if (receivedLoginPacket) { - GeyserImpl.getInstance().getLogger().warning("Received duplicate login packet from " + session.name()); session.disconnect("Received duplicate login packet!"); + session.forciblyCloseUpstream(); return PacketSignal.HANDLED; } receivedLoginPacket = true; @@ -219,7 +217,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { } if (geyser.getSessionManager().isXuidAlreadyPending(session.xuid()) || geyser.getSessionManager().sessionByXuid(session.xuid()) != null) { - session.disconnect(GeyserLocale.getLocaleStringLog("geyser.auth.already_loggedin", session.name())); + session.disconnect(GeyserLocale.getLocaleStringLog("geyser.auth.already_loggedin", session.bedrockUsername())); return PacketSignal.HANDLED; } @@ -233,7 +231,11 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { session.sendUpstreamPacket(playStatus); this.resourcePackLoadEvent = new SessionLoadResourcePacksEventImpl(session); - this.geyser.eventBus().fire(this.resourcePackLoadEvent); + this.geyser.geyserEventBus().fireEventElseKick(this.resourcePackLoadEvent, session); + if (session.isClosed()) { + // Can happen if an error occurs in the resource pack event; that'll disconnect the player + return PacketSignal.HANDLED; + } ResourcePacksInfoPacket resourcePacksInfo = new ResourcePacksInfoPacket(); resourcePacksInfo.getResourcePackInfos().addAll(this.resourcePackLoadEvent.infoPacketEntries()); @@ -267,6 +269,12 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.network.connect", session.getAuthData().name())); } case SEND_PACKS -> { + if (packet.getPackIds().isEmpty()) { + GeyserImpl.getInstance().getLogger().warning("Received empty pack ids in resource pack response packet!"); + session.disconnect("Invalid resource pack response packet received!"); + chunkRequestQueue.clear(); + return PacketSignal.HANDLED; + } packsToSend.addAll(packet.getPackIds()); sendPackDataInfo(packsToSend.pop()); } @@ -322,7 +330,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { @Override public PacketSignal handle(PlayerAuthInputPacket packet) { // This doesn't catch rotation, but for a niche case I don't exactly want to cache rotation... - if (session.isLoggingIn() && !packet.getMotion().equals(Vector2f.ZERO)) { + if (!session.isClosed() && session.isLoggingIn() && !packet.getMotion().equals(Vector2f.ZERO)) { SetTitlePacket titlePacket = new SetTitlePacket(); titlePacket.setType(SetTitlePacket.Type.ACTIONBAR); titlePacket.setText(GeyserLocale.getPlayerLocaleString("geyser.auth.login.wait", session.locale())); @@ -339,10 +347,16 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { @Override public PacketSignal handle(ResourcePackChunkRequestPacket packet) { + if (session.isClosed()) { + return PacketSignal.HANDLED; + } + if (finishedResourcePackSending) { + GeyserImpl.getInstance().getLogger().warning("Received resource pack chunk packet after stage completed! " + packet.toString()); session.disconnect("Illegal duplicate resource pack packet received!"); return PacketSignal.HANDLED; } + // Resolve some console pack downloading issues. // See for reference chunkRequestQueue.add(packet); @@ -359,17 +373,16 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { public void processNextChunk() { ResourcePackChunkRequestPacket packet = chunkRequestQueue.poll(); - if (packet == null) { + if (packet == null || session.isClosed()) { currentlySendingChunks = false; return; } ResourcePackHolder holder = this.resourcePackLoadEvent.getPacks().get(packet.getPackId()); - if (holder == null) { GeyserImpl.getInstance().getLogger().debug("Client {0} tried to request pack id {1} not sent to it!", session.bedrockUsername(), packet.getPackId()); - currentlySendingChunks = false; + chunkRequestQueue.clear(); session.disconnect("disconnectionScreen.resourcePack"); return; } @@ -380,7 +393,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { ResourcePackLoader.testRemotePack(session, urlPackCodec, holder); if (!resourcePackLoadEvent.value(holder.uuid(), ResourcePackOption.Type.FALLBACK, true)) { session.disconnect("Unable to provide downloaded resource pack. Contact an administrator!"); - currentlySendingChunks = false; + chunkRequestQueue.clear(); return; } }