mirror of
https://github.com/FabricMC/fabric.git
synced 2024-11-14 19:25:23 -05:00
Fix race condition when handling unknown packets. (#3508)
This commit is contained in:
parent
1681346ec9
commit
875cc147cf
2 changed files with 41 additions and 6 deletions
|
@ -16,7 +16,10 @@
|
|||
|
||||
package net.fabricmc.fabric.mixin.networking.client;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
@ -32,6 +35,10 @@ import net.fabricmc.fabric.impl.networking.payload.RetainedPayload;
|
|||
|
||||
@Mixin(ClientCommonNetworkHandler.class)
|
||||
public abstract class ClientCommonNetworkHandlerMixin implements NetworkHandlerExtensions {
|
||||
@Shadow
|
||||
@Final
|
||||
private static Logger LOGGER;
|
||||
|
||||
@Inject(method = "onCustomPayload(Lnet/minecraft/network/packet/s2c/common/CustomPayloadS2CPacket;)V", at = @At("HEAD"), cancellable = true)
|
||||
public void onCustomPayload(CustomPayloadS2CPacket packet, CallbackInfo ci) {
|
||||
if (packet.payload() instanceof ResolvablePayload payload) {
|
||||
|
@ -45,14 +52,15 @@ public abstract class ClientCommonNetworkHandlerMixin implements NetworkHandlerE
|
|||
throw new IllegalStateException("Unknown network addon");
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
ci.cancel();
|
||||
} else if (payload instanceof RetainedPayload retained && retained.buf().refCnt() > 0) {
|
||||
// Vanilla forces to use the render thread for its payloads,
|
||||
// that means this method can get called multiple times.
|
||||
if (!handled && payload instanceof RetainedPayload retained && retained.buf().refCnt() > 0) {
|
||||
// Duplicate the vanilla log message, as we cancel further processing.
|
||||
LOGGER.warn("Unknown custom packet payload: {}", payload.id());
|
||||
|
||||
retained.buf().skipBytes(retained.buf().readableBytes());
|
||||
retained.buf().release();
|
||||
}
|
||||
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import static net.minecraft.server.command.CommandManager.argument;
|
|||
import static net.minecraft.server.command.CommandManager.literal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
|
@ -38,6 +39,7 @@ import net.minecraft.util.Identifier;
|
|||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||
import net.fabricmc.fabric.api.networking.v1.FabricPacket;
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketType;
|
||||
|
@ -47,6 +49,7 @@ import net.fabricmc.fabric.test.networking.NetworkingTestmods;
|
|||
public final class NetworkingPlayPacketTest implements ModInitializer {
|
||||
public static final Identifier TEST_CHANNEL = NetworkingTestmods.id("test_channel");
|
||||
private static final Identifier UNKNOWN_TEST_CHANNEL = NetworkingTestmods.id("unknown_test_channel");
|
||||
private static boolean spamUnknownPackets = false;
|
||||
|
||||
public static void sendToTestChannel(ServerPlayerEntity player, String stuff) {
|
||||
ServerPlayNetworking.getSender(player).sendPacket(new OverlayPacket(Text.literal(stuff)), future -> {
|
||||
|
@ -55,7 +58,13 @@ public final class NetworkingPlayPacketTest implements ModInitializer {
|
|||
}
|
||||
|
||||
private static void sendToUnknownChannel(ServerPlayerEntity player) {
|
||||
ServerPlayNetworking.getSender(player).sendPacket(UNKNOWN_TEST_CHANNEL, PacketByteBufs.create());
|
||||
PacketByteBuf buf = PacketByteBufs.create();
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
buf.writeUuid(UUID.randomUUID());
|
||||
}
|
||||
|
||||
ServerPlayNetworking.getSender(player).sendPacket(UNKNOWN_TEST_CHANNEL, buf);
|
||||
}
|
||||
|
||||
public static void registerCommand(CommandDispatcher<ServerCommandSource> dispatcher) {
|
||||
|
@ -71,6 +80,11 @@ public final class NetworkingPlayPacketTest implements ModInitializer {
|
|||
sendToUnknownChannel(ctx.getSource().getPlayer());
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}))
|
||||
.then(literal("spamUnknown").executes(ctx -> {
|
||||
spamUnknownPackets = true;
|
||||
ctx.getSource().sendMessage(Text.literal("Spamming unknown packets state:" + spamUnknownPackets));
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}))
|
||||
.then(literal("bufctor").executes(ctx -> {
|
||||
PacketByteBuf buf = PacketByteBufs.create();
|
||||
buf.writeIdentifier(TEST_CHANNEL);
|
||||
|
@ -106,6 +120,19 @@ public final class NetworkingPlayPacketTest implements ModInitializer {
|
|||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
NetworkingPlayPacketTest.registerCommand(dispatcher);
|
||||
});
|
||||
|
||||
ServerTickEvents.START_SERVER_TICK.register(server -> {
|
||||
if (!spamUnknownPackets) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send many unknown packets, used to debug https://github.com/FabricMC/fabric/issues/3505
|
||||
for (ServerPlayerEntity player : server.getPlayerManager().getPlayerList()) {
|
||||
for (int i = 0; i < 50; i++) {
|
||||
sendToUnknownChannel(player);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public record OverlayPacket(Text message) implements FabricPacket {
|
||||
|
|
Loading…
Reference in a new issue