1
0
mirror of https://github.com/GeyserMC/Floodgate.git synced 2025-12-28 19:19:15 +00:00

Fixed an issue with send-floodgate-data and player linking

This commit is contained in:
Tim203
2023-09-30 19:37:25 +02:00
parent f25673dcaa
commit dbccdd1f6e
9 changed files with 51 additions and 111 deletions

View File

@@ -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<String> kickMessageAttribute;
@Inject
@Named("playerAttribute")
private AttributeKey<Connection> 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;
}

View File

@@ -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<Connection> playerAttribute;
@Inject FloodgateDataCodec dataCodec;
@Inject
@Named("playerAttribute")
AttributeKey<Connection> 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
}

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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<String> kickMessageAttribute;
@Inject
@Named("playerAttribute")
AttributeKey<Connection> 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;
}

View File

@@ -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<Connection> 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);

View File

@@ -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;