diff --git a/bungee/base/src/main/java/org/geysermc/floodgate/bungee/addon/data/BungeeDataAddon.java b/bungee/base/src/main/java/org/geysermc/floodgate/bungee/addon/data/BungeeDataAddon.java index 020a9219..b6ad039e 100644 --- a/bungee/base/src/main/java/org/geysermc/floodgate/bungee/addon/data/BungeeDataAddon.java +++ b/bungee/base/src/main/java/org/geysermc/floodgate/bungee/addon/data/BungeeDataAddon.java @@ -30,10 +30,8 @@ import io.netty.util.AttributeKey; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; -import org.geysermc.api.connection.Connection; import org.geysermc.floodgate.api.inject.InjectorAddon; import org.geysermc.floodgate.core.addon.data.PacketBlocker; -import org.geysermc.floodgate.core.api.ProxyFloodgateApi; import org.geysermc.floodgate.core.config.ProxyFloodgateConfig; import org.geysermc.floodgate.core.connection.FloodgateHandshakeHandler; @@ -41,7 +39,6 @@ import org.geysermc.floodgate.core.connection.FloodgateHandshakeHandler; public class BungeeDataAddon implements InjectorAddon { @Inject private FloodgateHandshakeHandler handshakeHandler; @Inject private ProxyFloodgateConfig config; - @Inject private ProxyFloodgateApi api; @Inject @Named("packetHandler") @@ -59,18 +56,13 @@ public class BungeeDataAddon implements InjectorAddon { @Named("kickMessageAttribute") private AttributeKey kickMessageAttribute; - @Inject - @Named("playerAttribute") - private AttributeKey playerAttribute; + @Inject BungeeServerDataHandler serverDataHandler; @Override public void onInject(Channel channel, boolean toServer) { if (toServer) { if (config.sendFloodgateData()) { - channel.pipeline().addAfter( - packetEncoder, "floodgate_data_handler", - new BungeeServerDataHandler(api, playerAttribute) - ); + channel.pipeline().addAfter(packetEncoder, "floodgate_data_handler", serverDataHandler); } return; } diff --git a/bungee/base/src/main/java/org/geysermc/floodgate/bungee/addon/data/BungeeServerDataHandler.java b/bungee/base/src/main/java/org/geysermc/floodgate/bungee/addon/data/BungeeServerDataHandler.java index 91a6e795..2534d32a 100644 --- a/bungee/base/src/main/java/org/geysermc/floodgate/bungee/addon/data/BungeeServerDataHandler.java +++ b/bungee/base/src/main/java/org/geysermc/floodgate/bungee/addon/data/BungeeServerDataHandler.java @@ -27,12 +27,15 @@ package org.geysermc.floodgate.bungee.addon.data; import static java.util.Objects.requireNonNull; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelOutboundHandlerAdapter; import io.netty.channel.ChannelPromise; import io.netty.util.AttributeKey; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.inject.Singleton; import java.lang.reflect.Field; -import lombok.RequiredArgsConstructor; import net.md_5.bungee.ServerConnector; import net.md_5.bungee.UserConnection; import net.md_5.bungee.netty.ChannelWrapper; @@ -40,13 +43,13 @@ import net.md_5.bungee.netty.HandlerBoss; import net.md_5.bungee.netty.PacketHandler; import net.md_5.bungee.protocol.packet.Handshake; import org.geysermc.api.connection.Connection; -import org.geysermc.floodgate.core.api.ProxyFloodgateApi; import org.geysermc.floodgate.core.connection.FloodgateConnection; +import org.geysermc.floodgate.core.crypto.FloodgateDataCodec; import org.geysermc.floodgate.core.util.ReflectionUtils; -import org.geysermc.floodgate.util.BedrockData; +@Singleton +@ChannelHandler.Sharable @SuppressWarnings("ConstantConditions") -@RequiredArgsConstructor public class BungeeServerDataHandler extends ChannelOutboundHandlerAdapter { private static final Field HANDLER; private static final Field USER_CONNECTION; @@ -64,11 +67,14 @@ public class BungeeServerDataHandler extends ChannelOutboundHandlerAdapter { requireNonNull(CHANNEL_WRAPPER, "ChannelWrapper field cannot be null"); } - private final ProxyFloodgateApi api; - private final AttributeKey playerAttribute; + @Inject FloodgateDataCodec dataCodec; + + @Inject + @Named("playerAttribute") + AttributeKey playerAttribute; @Override - public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) { + public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception { if (packet instanceof Handshake) { // get the Proxy <-> Player channel from the Proxy <-> Server channel HandlerBoss handlerBoss = ctx.pipeline().get(HandlerBoss.class); @@ -80,14 +86,12 @@ public class BungeeServerDataHandler extends ChannelOutboundHandlerAdapter { return; } - UserConnection connection = ReflectionUtils.getCastedValue(handler, USER_CONNECTION); - ChannelWrapper wrapper = ReflectionUtils.getCastedValue(connection, CHANNEL_WRAPPER); + UserConnection userConnection = ReflectionUtils.getCastedValue(handler, USER_CONNECTION); + ChannelWrapper wrapper = ReflectionUtils.getCastedValue(userConnection, CHANNEL_WRAPPER); - Connection player = wrapper.getHandle().attr(playerAttribute).get(); - - if (player != null) { - BedrockData data = ((FloodgateConnection) player).toBedrockData(); - String encryptedData = api.createEncryptedDataString(data); + Connection connection = wrapper.getHandle().attr(playerAttribute).get(); + if (connection != null) { + String encodedData = dataCodec.encodeToString((FloodgateConnection) connection); Handshake handshake = (Handshake) packet; String address = handshake.getHost(); @@ -104,7 +108,7 @@ public class BungeeServerDataHandler extends ChannelOutboundHandlerAdapter { remaining = ""; } - handshake.setHost(originalAddress + '\0' + encryptedData + remaining); + handshake.setHost(originalAddress + '\0' + encodedData + remaining); // Bungeecord will add its data after our data } diff --git a/bungee/base/src/main/java/org/geysermc/floodgate/bungee/listener/BungeeListener.java b/bungee/base/src/main/java/org/geysermc/floodgate/bungee/listener/BungeeListener.java index dba341b3..c98036ee 100644 --- a/bungee/base/src/main/java/org/geysermc/floodgate/bungee/listener/BungeeListener.java +++ b/bungee/base/src/main/java/org/geysermc/floodgate/bungee/listener/BungeeListener.java @@ -44,7 +44,7 @@ import net.md_5.bungee.event.EventPriority; import org.geysermc.api.connection.Connection; import org.geysermc.floodgate.api.logger.FloodgateLogger; import org.geysermc.floodgate.bungee.player.BungeeConnectionManager; -import org.geysermc.floodgate.core.api.ProxyFloodgateApi; +import org.geysermc.floodgate.core.api.SimpleFloodgateApi; import org.geysermc.floodgate.core.config.ProxyFloodgateConfig; import org.geysermc.floodgate.core.listener.McListener; import org.geysermc.floodgate.core.skin.SkinApplier; @@ -64,7 +64,7 @@ public final class BungeeListener implements Listener, McListener { @Inject BungeeConnectionManager connectionManager; @Inject ProxyFloodgateConfig config; - @Inject ProxyFloodgateApi api; + @Inject SimpleFloodgateApi api; @Inject LanguageManager languageManager; @Inject FloodgateLogger logger; @Inject SkinApplier skinApplier; diff --git a/core/src/main/java/org/geysermc/floodgate/core/api/ProxyFloodgateApi.java b/core/src/main/java/org/geysermc/floodgate/core/api/ProxyFloodgateApi.java deleted file mode 100644 index 339eb08e..00000000 --- a/core/src/main/java/org/geysermc/floodgate/core/api/ProxyFloodgateApi.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * @author GeyserMC - * @link https://github.com/GeyserMC/Floodgate - */ - -package org.geysermc.floodgate.core.api; - -import jakarta.inject.Inject; -import jakarta.inject.Singleton; -import java.nio.charset.StandardCharsets; -import org.geysermc.floodgate.core.crypto.FloodgateFormatCodec; -import org.geysermc.floodgate.core.scope.ProxyOnly; -import org.geysermc.floodgate.util.BedrockData; - -@ProxyOnly -@Singleton -public final class ProxyFloodgateApi extends SimpleFloodgateApi { - @Inject FloodgateFormatCodec dataCodec; - - public byte[] createEncryptedData(BedrockData bedrockData) { - try { - return dataCodec.encodeFromString(bedrockData.toString()); - } catch (Exception exception) { - throw new IllegalStateException("We failed to create the encrypted data, " + - "but creating encrypted data is mandatory!", exception); - } - } - - public String createEncryptedDataString(BedrockData bedrockData) { - return new String(createEncryptedData(bedrockData), StandardCharsets.UTF_8); - } -} diff --git a/core/src/main/java/org/geysermc/floodgate/core/api/SimpleFloodgateApi.java b/core/src/main/java/org/geysermc/floodgate/core/api/SimpleFloodgateApi.java index 47ff063c..f28a70aa 100644 --- a/core/src/main/java/org/geysermc/floodgate/core/api/SimpleFloodgateApi.java +++ b/core/src/main/java/org/geysermc/floodgate/core/api/SimpleFloodgateApi.java @@ -46,9 +46,7 @@ import org.geysermc.floodgate.core.http.xbox.XboxClient; import org.geysermc.floodgate.core.pluginmessage.PluginMessageManager; import org.geysermc.floodgate.core.pluginmessage.channel.FormChannel; import org.geysermc.floodgate.core.pluginmessage.channel.TransferChannel; -import org.geysermc.floodgate.core.scope.ServerOnly; -@ServerOnly @Singleton public class SimpleFloodgateApi implements GeyserApiBase { @Inject ConnectionManager connectionManager; diff --git a/core/src/main/java/org/geysermc/floodgate/core/connection/FloodgateHandshakeHandler.java b/core/src/main/java/org/geysermc/floodgate/core/connection/FloodgateHandshakeHandler.java index 575202c1..2a7f5f24 100644 --- a/core/src/main/java/org/geysermc/floodgate/core/connection/FloodgateHandshakeHandler.java +++ b/core/src/main/java/org/geysermc/floodgate/core/connection/FloodgateHandshakeHandler.java @@ -111,7 +111,6 @@ public final class FloodgateHandshakeHandler { @NonNull String floodgateDataString, @NonNull String hostname ) { - System.out.println("received: " + floodgateDataString); byte[] floodgateData = floodgateDataString.getBytes(StandardCharsets.UTF_8); return CompletableFuture.supplyAsync(() -> { @@ -132,7 +131,7 @@ public final class FloodgateHandshakeHandler { throw callHandlerAndReturnResult(INVALID_DATA, channel, hostname); } catch (Exception exception) { // all the other exceptions are caused by invalid/tempered Floodgate data - if (config.debug() || true) { + if (config.debug()) { exception.printStackTrace(); } @@ -235,7 +234,7 @@ public final class FloodgateHandshakeHandler { return link.fetchLink(Utils.getJavaUuid(data.xuid())) .thenApply(link -> { if (link == null) { - return null; + return data; } var linked = LinkedPlayer.of(link.javaUsername(), link.javaUniqueId(), link.bedrockId()); return new FloodgateConnectionBuilder(config).linkedPlayer(linked).build(); diff --git a/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityDataAddon.java b/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityDataAddon.java index 47121c41..7deb8924 100644 --- a/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityDataAddon.java +++ b/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityDataAddon.java @@ -30,11 +30,9 @@ import io.netty.util.AttributeKey; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; -import org.geysermc.api.connection.Connection; import org.geysermc.floodgate.api.inject.InjectorAddon; import org.geysermc.floodgate.api.logger.FloodgateLogger; import org.geysermc.floodgate.core.addon.data.PacketBlocker; -import org.geysermc.floodgate.core.api.ProxyFloodgateApi; import org.geysermc.floodgate.core.config.ProxyFloodgateConfig; import org.geysermc.floodgate.core.connection.FloodgateHandshakeHandler; @@ -42,7 +40,6 @@ import org.geysermc.floodgate.core.connection.FloodgateHandshakeHandler; public final class VelocityDataAddon implements InjectorAddon { @Inject FloodgateHandshakeHandler handshakeHandler; @Inject ProxyFloodgateConfig config; - @Inject ProxyFloodgateApi api; @Inject FloodgateLogger logger; @Inject @@ -62,17 +59,13 @@ public final class VelocityDataAddon implements InjectorAddon { AttributeKey kickMessageAttribute; @Inject - @Named("playerAttribute") - AttributeKey playerAttribute; + VelocityServerDataHandler serverDataHandler; @Override public void onInject(Channel channel, boolean toServer) { if (toServer) { if (config.sendFloodgateData()) { - channel.pipeline().addAfter( - packetEncoder, "floodgate_data_handler", - new VelocityServerDataHandler(api) - ); + channel.pipeline().addAfter(packetEncoder, "floodgate_data_handler", serverDataHandler); } return; } diff --git a/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityServerDataHandler.java b/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityServerDataHandler.java index ee64b6f9..327e383f 100644 --- a/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityServerDataHandler.java +++ b/velocity/base/src/main/java/org/geysermc/floodgate/velocity/addon/data/VelocityServerDataHandler.java @@ -35,16 +35,23 @@ import static org.geysermc.floodgate.core.util.ReflectionUtils.invoke; import static org.geysermc.floodgate.core.util.ReflectionUtils.setValue; import com.velocitypowered.api.proxy.Player; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelOutboundHandlerAdapter; import io.netty.channel.ChannelPromise; +import io.netty.util.AttributeKey; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.inject.Singleton; import java.lang.reflect.Field; import java.lang.reflect.Method; import org.geysermc.api.connection.Connection; -import org.geysermc.floodgate.core.api.ProxyFloodgateApi; +import org.geysermc.floodgate.core.api.SimpleFloodgateApi; import org.geysermc.floodgate.core.connection.FloodgateConnection; -import org.geysermc.floodgate.util.BedrockData; +import org.geysermc.floodgate.core.crypto.FloodgateDataCodec; +@Singleton +@ChannelHandler.Sharable @SuppressWarnings("ConstantConditions") public final class VelocityServerDataHandler extends ChannelOutboundHandlerAdapter { private static final Class HANDSHAKE_PACKET; @@ -70,30 +77,30 @@ public final class VelocityServerDataHandler extends ChannelOutboundHandlerAdapt requireNonNull(GET_PLAYER, "getPlayer in VelocityServerConnection cannot be null"); } - private final ProxyFloodgateApi api; + @Inject SimpleFloodgateApi api; + @Inject FloodgateDataCodec dataCodec; - public VelocityServerDataHandler(ProxyFloodgateApi api) { - this.api = api; - } + @Inject + @Named("playerAttribute") + AttributeKey playerAttribute; @Override - public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) - throws Exception { + public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception { if (HANDSHAKE_PACKET.isInstance(packet)) { String address = getCastedValue(packet, HANDSHAKE_ADDRESS); + // The connection to the backend server is not the same connection as the client to the proxy. + // This gets the client to proxy Connection from the backend server connection. + // get the FloodgatePlayer from the ConnectedPlayer Object minecraftConnection = ctx.pipeline().get("handler"); Object association = invoke(minecraftConnection, GET_ASSOCIATION); Player velocityPlayer = castedInvoke(association, GET_PLAYER); - //noinspection ConstantConditions - Connection player = api.connectionByUuid(velocityPlayer.getUniqueId()); - - if (player != null) { + Connection connection = api.connectionByUuid(velocityPlayer.getUniqueId()); + if (connection != null) { // Player is a Floodgate player - BedrockData data = ((FloodgateConnection) player).toBedrockData(); - String encryptedData = api.createEncryptedDataString(data); + String encodedData = dataCodec.encodeToString((FloodgateConnection) connection); // use the same system that we use on bungee, our data goes before all the other data int addressFinished = address.indexOf('\0'); @@ -109,8 +116,7 @@ public final class VelocityServerDataHandler extends ChannelOutboundHandlerAdapt remaining = address.substring(addressFinished); } - setValue(packet, HANDSHAKE_ADDRESS, originalAddress + '\0' + encryptedData - + remaining); + setValue(packet, HANDSHAKE_ADDRESS, originalAddress + '\0' + encodedData + remaining); } ctx.pipeline().remove(this); diff --git a/velocity/base/src/main/java/org/geysermc/floodgate/velocity/listener/VelocityListener.java b/velocity/base/src/main/java/org/geysermc/floodgate/velocity/listener/VelocityListener.java index 3fac6871..1cf60512 100644 --- a/velocity/base/src/main/java/org/geysermc/floodgate/velocity/listener/VelocityListener.java +++ b/velocity/base/src/main/java/org/geysermc/floodgate/velocity/listener/VelocityListener.java @@ -42,7 +42,7 @@ import java.util.Collections; import net.kyori.adventure.text.Component; import org.geysermc.api.connection.Connection; import org.geysermc.floodgate.api.logger.FloodgateLogger; -import org.geysermc.floodgate.core.api.ProxyFloodgateApi; +import org.geysermc.floodgate.core.api.SimpleFloodgateApi; import org.geysermc.floodgate.core.config.ProxyFloodgateConfig; import org.geysermc.floodgate.core.listener.McListener; import org.geysermc.floodgate.core.util.LanguageManager; @@ -52,7 +52,7 @@ import org.geysermc.floodgate.velocity.player.VelocityConnectionManager; public final class VelocityListener implements McListener { @Inject VelocityConnectionManager connectionManager; @Inject ProxyFloodgateConfig config; - @Inject ProxyFloodgateApi api; + @Inject SimpleFloodgateApi api; @Inject LanguageManager languageManager; @Inject FloodgateLogger logger;