diff --git a/common/src/main/java/org/geysermc/floodgate/FloodgatePlatform.java b/common/src/main/java/org/geysermc/floodgate/FloodgatePlatform.java index de6429b0..58706ac4 100644 --- a/common/src/main/java/org/geysermc/floodgate/FloodgatePlatform.java +++ b/common/src/main/java/org/geysermc/floodgate/FloodgatePlatform.java @@ -50,7 +50,6 @@ import org.geysermc.floodgate.news.NewsChecker; import org.geysermc.floodgate.util.FloodgateInfoHolder; import org.geysermc.floodgate.util.GitProperties; import org.geysermc.floodgate.util.PrefixCheckTask; -import org.geysermc.floodgate.util.TimeSyncerHolder; public class FloodgatePlatform { private static final UUID KEY = UUID.randomUUID(); @@ -104,11 +103,6 @@ public class FloodgatePlatform { guice = guice.createChildInjector(new ConfigLoadedModule(config)); PlayerLink link = guice.getInstance(PlayerLinkLoader.class).load(); - if (config.isProxy()) { - // We can't assume, for now, that the backend Floodgate instances are updated to remove this - TimeSyncerHolder.init(); - } - InstanceHolder.set(api, link, this.injector, packetHandlers, handshakeHandlers, KEY); // for Geyser dump diff --git a/common/src/main/java/org/geysermc/floodgate/addon/data/CommonDataHandler.java b/common/src/main/java/org/geysermc/floodgate/addon/data/CommonDataHandler.java index 9bdddaae..94271a8c 100644 --- a/common/src/main/java/org/geysermc/floodgate/addon/data/CommonDataHandler.java +++ b/common/src/main/java/org/geysermc/floodgate/addon/data/CommonDataHandler.java @@ -30,14 +30,15 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.AttributeKey; -import it.unimi.dsi.fastutil.Pair; import java.net.InetSocketAddress; import java.util.Queue; import lombok.RequiredArgsConstructor; import org.geysermc.floodgate.api.handshake.HandshakeData; import org.geysermc.floodgate.config.FloodgateConfig; +import org.geysermc.floodgate.crypto.FloodgateCipher; import org.geysermc.floodgate.player.FloodgateHandshakeHandler; import org.geysermc.floodgate.player.FloodgateHandshakeHandler.HandshakeResult; +import org.geysermc.floodgate.player.HostnameSeparationResult; import org.geysermc.floodgate.util.Constants; @RequiredArgsConstructor @@ -67,20 +68,26 @@ public abstract class CommonDataHandler extends ChannelInboundHandlerAdapter { protected void handle(Object handshakePacket, String hostname) { this.handshakePacket = handshakePacket; - Pair separated = handshakeHandler.separateHostname(hostname); + HostnameSeparationResult separation = handshakeHandler.separateHostname(hostname); - if (separated.left() == null) { + if (separation.floodgateData() == null) { // not a Floodgate player, make sure to resend the cancelled handshake packet disablePacketQueue(true); return; } + if (separation.headerVersion() != FloodgateCipher.VERSION) { + disablePacketQueue(true); + setKickMessage(Constants.UNSUPPORTED_DATA_VERSION); + return; + } + blocker.enable(); Channel channel = ctx.channel(); handshakeHandler - .handle(channel, separated.left(), separated.right()) + .handle(channel, separation.floodgateData(), separation.hostnameRemainder()) .thenApply(result -> { HandshakeData handshakeData = result.getHandshakeData(); diff --git a/common/src/main/java/org/geysermc/floodgate/command/main/FirewallCheckSubcommand.java b/common/src/main/java/org/geysermc/floodgate/command/main/FirewallCheckSubcommand.java index 791e1746..50245e39 100644 --- a/common/src/main/java/org/geysermc/floodgate/command/main/FirewallCheckSubcommand.java +++ b/common/src/main/java/org/geysermc/floodgate/command/main/FirewallCheckSubcommand.java @@ -25,7 +25,6 @@ package org.geysermc.floodgate.command.main; -import static org.geysermc.floodgate.time.SntpClientUtils.requestTimeOffset; import static org.geysermc.floodgate.util.Constants.COLOR_CHAR; import cloud.commandframework.context.CommandContext; @@ -46,8 +45,7 @@ final class FirewallCheckSubcommand { static void executeFirewall(CommandContext context) { UserAudience sender = context.getSender(); executeChecks( - globalApiCheck(sender), - timeSyncCheck(sender) + globalApiCheck(sender) ).whenComplete((response, $) -> sender.sendMessage(String.format( COLOR_CHAR + "eThe checks have finished. %s/%s were successful", @@ -72,18 +70,6 @@ final class FirewallCheckSubcommand { }); } - private static BooleanSupplier timeSyncCheck(UserAudience sender) { - return executeFirewallText(sender, "time sync", () -> { - // UDP packets can get lost - for (int i = 0; i < 3; i++) { - if (requestTimeOffset(Constants.NTP_SERVER, 2000) != Long.MIN_VALUE) { - return; - } - } - throw new IllegalStateException("Failed to receive time offset"); - }); - } - private static BooleanSupplier executeFirewallText( UserAudience sender, String name, Runnable runnable) { return () -> { diff --git a/common/src/main/java/org/geysermc/floodgate/player/FloodgateHandshakeHandler.java b/common/src/main/java/org/geysermc/floodgate/player/FloodgateHandshakeHandler.java index 507772a6..4240808a 100644 --- a/common/src/main/java/org/geysermc/floodgate/player/FloodgateHandshakeHandler.java +++ b/common/src/main/java/org/geysermc/floodgate/player/FloodgateHandshakeHandler.java @@ -91,20 +91,23 @@ public final class FloodgateHandshakeHandler { * @return The first string is the Floodgate data (or null if there isn't) and the second string * is the hostname without the Floodgate. */ - public Pair separateHostname(@NonNull String hostname) { + public HostnameSeparationResult separateHostname(@NonNull String hostname) { String[] hostnameItems = hostname.split("\0"); String floodgateData = null; + int dataVersion = -1; StringBuilder hostnameBuilder = new StringBuilder(); for (String value : hostnameItems) { - if (floodgateData == null && FloodgateCipher.hasHeader(value)) { + int version = FloodgateCipher.version(value); + if (floodgateData == null && version != -1) { floodgateData = value; + dataVersion = version; continue; } hostnameBuilder.append(value).append('\0'); } // hostname now doesn't have Floodgate data anymore if it had - return Pair.of(floodgateData, hostnameBuilder.toString()); + return new HostnameSeparationResult(floodgateData, dataVersion, hostnameBuilder.toString()); } public CompletableFuture handle( diff --git a/common/src/main/java/org/geysermc/floodgate/player/FloodgatePlayerImpl.java b/common/src/main/java/org/geysermc/floodgate/player/FloodgatePlayerImpl.java index 08593093..d65841d4 100644 --- a/common/src/main/java/org/geysermc/floodgate/player/FloodgatePlayerImpl.java +++ b/common/src/main/java/org/geysermc/floodgate/player/FloodgatePlayerImpl.java @@ -39,12 +39,10 @@ import org.geysermc.floodgate.api.handshake.HandshakeData; import org.geysermc.floodgate.api.player.FloodgatePlayer; import org.geysermc.floodgate.api.player.PropertyKey; import org.geysermc.floodgate.api.player.PropertyKey.Result; -import org.geysermc.floodgate.time.TimeSyncer; import org.geysermc.floodgate.util.BedrockData; import org.geysermc.floodgate.util.DeviceOs; import org.geysermc.floodgate.util.InputMode; import org.geysermc.floodgate.util.LinkedPlayer; -import org.geysermc.floodgate.util.TimeSyncerHolder; import org.geysermc.floodgate.util.UiProfile; import org.geysermc.floodgate.util.Utils; @@ -84,9 +82,9 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer { UUID javaUniqueId = Utils.getJavaUuid(data.getXuid()); - DeviceOs deviceOs = DeviceOs.getById(data.getDeviceOs()); - UiProfile uiProfile = UiProfile.getById(data.getUiProfile()); - InputMode inputMode = InputMode.getById(data.getInputMode()); + DeviceOs deviceOs = DeviceOs.fromId(data.getDeviceOs()); + UiProfile uiProfile = UiProfile.fromId(data.getUiProfile()); + InputMode inputMode = InputMode.fromId(data.getInputMode()); LinkedPlayer linkedPlayer = handshakeData.getLinkedPlayer(); @@ -113,11 +111,9 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer { } public BedrockData toBedrockData() { - TimeSyncer timeSyncer = TimeSyncerHolder.get(); - return BedrockData.of(version, username, xuid, deviceOs.ordinal(), languageCode, uiProfile.ordinal(), inputMode.ordinal(), ip, linkedPlayer, proxy, subscribeId, - verifyCode, timeSyncer); + verifyCode); } @Override diff --git a/common/src/main/java/org/geysermc/floodgate/util/TimeSyncerHolder.java b/common/src/main/java/org/geysermc/floodgate/player/HostnameSeparationResult.java similarity index 64% rename from common/src/main/java/org/geysermc/floodgate/util/TimeSyncerHolder.java rename to common/src/main/java/org/geysermc/floodgate/player/HostnameSeparationResult.java index 09627134..76081c69 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/TimeSyncerHolder.java +++ b/common/src/main/java/org/geysermc/floodgate/player/HostnameSeparationResult.java @@ -23,22 +23,29 @@ * @link https://github.com/GeyserMC/Floodgate */ -package org.geysermc.floodgate.util; +package org.geysermc.floodgate.player; -import org.geysermc.floodgate.time.TimeSyncer; +public class HostnameSeparationResult { + private final String floodgateData; + private final int headerVersion; + private final String hostnameRemainder; -public final class TimeSyncerHolder { - private static TimeSyncer timeSyncer; - - public static void init() { - timeSyncer = new TimeSyncer(Constants.NTP_SERVER); + public HostnameSeparationResult( + String floodgateData, int headerVersion, String hostnameRemainder) { + this.floodgateData = floodgateData; + this.headerVersion = headerVersion; + this.hostnameRemainder = hostnameRemainder; } - public static void set(TimeSyncer syncer) { - timeSyncer = syncer; + public String floodgateData() { + return floodgateData; } - public static TimeSyncer get() { - return timeSyncer; + public int headerVersion() { + return headerVersion; + } + + public String hostnameRemainder() { + return hostnameRemainder; } } diff --git a/common/src/main/java/org/geysermc/floodgate/skin/SkinUploadSocket.java b/common/src/main/java/org/geysermc/floodgate/skin/SkinUploadSocket.java index 5eb70204..6ec1d31e 100644 --- a/common/src/main/java/org/geysermc/floodgate/skin/SkinUploadSocket.java +++ b/common/src/main/java/org/geysermc/floodgate/skin/SkinUploadSocket.java @@ -95,7 +95,7 @@ final class SkinUploadSocket extends WebSocketClient { } int typeId = message.get("event_id").getAsInt(); - WebsocketEventType type = WebsocketEventType.getById(typeId); + WebsocketEventType type = WebsocketEventType.fromId(typeId); if (type == null) { logger.warn("Got unknown type {}. Ensure that Floodgate is up-to-date", typeId); return; diff --git a/common/src/main/java/org/geysermc/floodgate/util/Constants.java b/common/src/main/java/org/geysermc/floodgate/util/Constants.java index 23267e14..48978479 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/Constants.java +++ b/common/src/main/java/org/geysermc/floodgate/util/Constants.java @@ -52,6 +52,10 @@ public final class Constants { public static final String INTERNAL_ERROR_MESSAGE = "An internal error happened while handling Floodgate data." + " Try logging in again or contact a server administrator if the issue persists."; + public static final String UNSUPPORTED_DATA_VERSION = + "Received an unsupported Floodgate data version." + + " This Floodgate version is made for data version %s, received %s." + + " Make sure that Floodgate is up-to-date."; public static final int HANDSHAKE_PACKET_ID = 0; diff --git a/pom.xml b/pom.xml index fb9c9f7a..d8761f03 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ - 1.4.3-SNAPSHOT + 2.0.0-SNAPSHOT 1.0-SNAPSHOT 1.13-R0.1-SNAPSHOT 8.5.3