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

Moved some common data handling logic to the common module

This commit is contained in:
Tim203
2021-11-07 14:51:37 +01:00
parent 0bb3693dfa
commit 2d2c38e120
9 changed files with 434 additions and 351 deletions

View File

@@ -79,7 +79,7 @@ public class BungeeDataAddon implements InjectorAddon {
channel.pipeline().addBefore(
packetHandler, "floodgate_data_handler",
new BungeeProxyDataHandler(config, handshakeHandler, blocker, kickMessageAttribute)
new BungeeProxyDataHandler(handshakeHandler, config, kickMessageAttribute, blocker)
);
}

View File

@@ -27,30 +27,22 @@ package org.geysermc.floodgate.addon.data;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.Queues;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.Channel;
import io.netty.util.AttributeKey;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;
import java.util.Queue;
import java.util.concurrent.CompletableFuture;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.netty.ChannelWrapper;
import net.md_5.bungee.netty.HandlerBoss;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.PacketWrapper;
import net.md_5.bungee.protocol.packet.Handshake;
import org.geysermc.floodgate.api.handshake.HandshakeData;
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
import org.geysermc.floodgate.player.FloodgateHandshakeHandler;
import org.geysermc.floodgate.util.Constants;
import org.geysermc.floodgate.util.ReflectionUtils;
@SuppressWarnings("ConstantConditions")
@RequiredArgsConstructor
public class BungeeProxyDataHandler extends ChannelInboundHandlerAdapter {
public class BungeeProxyDataHandler extends CommonDataHandler {
private static final Field HANDLER;
private static final Field CHANNEL_WRAPPER;
@@ -63,100 +55,45 @@ public class BungeeProxyDataHandler extends ChannelInboundHandlerAdapter {
checkNotNull(CHANNEL_WRAPPER, "ChannelWrapper field cannot be null");
}
private final ProxyFloodgateConfig config;
private final FloodgateHandshakeHandler handler;
private final PacketBlocker blocker;
private final AttributeKey<String> kickMessageAttribute;
private final Queue<Object> packetQueue = Queues.newConcurrentLinkedQueue();
public BungeeProxyDataHandler(
FloodgateHandshakeHandler handshakeHandler,
ProxyFloodgateConfig config,
AttributeKey<String> kickMessageAttribute,
PacketBlocker blocker) {
super(handshakeHandler, config, kickMessageAttribute, blocker);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
// prevent other packets from being handled while we handle the handshake packet
if (!packetQueue.isEmpty()) {
packetQueue.add(msg);
return;
}
protected void setNewIp(Channel channel, InetSocketAddress newIp) {
HandlerBoss handlerBoss = ctx.pipeline().get(HandlerBoss.class);
// InitialHandler extends PacketHandler and implements PendingConnection
InitialHandler connection = ReflectionUtils.getCastedValue(handlerBoss, HANDLER);
ChannelWrapper channelWrapper = ReflectionUtils.getCastedValue(connection, CHANNEL_WRAPPER);
channelWrapper.setRemoteAddress(newIp);
}
@Override
protected void setHostname(Object wrapperWithHandshake, String hostname) {
PacketWrapper wrapper = (PacketWrapper) wrapperWithHandshake;
Handshake handshake = (Handshake) wrapper.packet;
handshake.setHost(hostname);
}
@Override
public boolean channelRead(Object msg) {
if (msg instanceof PacketWrapper) {
DefinedPacket packet = ((PacketWrapper) msg).packet;
// we're only interested in the Handshake packet
if (packet instanceof Handshake) {
blocker.enable();
packetQueue.add(msg);
handle(msg, ((Handshake) packet).getHost());
handleHandshake(ctx, (Handshake) packet).thenRun(() -> {
Object queuedPacket;
while ((queuedPacket = packetQueue.poll()) != null) {
ctx.fireChannelRead(queuedPacket);
}
ctx.pipeline().remove(this);
blocker.disable();
});
return;
// otherwise, it'll get read twice. once by the packet queue and once by this method
return false;
}
}
ctx.fireChannelRead(msg);
}
private CompletableFuture<Void> handleHandshake(ChannelHandlerContext ctx, Handshake packet) {
String data = packet.getHost();
return handler.handle(ctx.channel(), data).thenAccept(result -> {
HandshakeData handshakeData = result.getHandshakeData();
// we'll change the IP address from the proxy to the real IP of the client very early on
// so that almost every plugin will use the real IP of the client
InetSocketAddress newIp = result.getNewIp(ctx.channel());
if (newIp != null) {
HandlerBoss handlerBoss = ctx.pipeline().get(HandlerBoss.class);
// InitialHandler extends PacketHandler and implements PendingConnection
InitialHandler connection = ReflectionUtils.getCastedValue(handlerBoss, HANDLER);
ChannelWrapper channelWrapper =
ReflectionUtils.getCastedValue(connection, CHANNEL_WRAPPER);
channelWrapper.setRemoteAddress(newIp);
}
packet.setHost(handshakeData.getHostname());
if (handshakeData.getDisconnectReason() != null) {
ctx.channel().attr(kickMessageAttribute).set(handshakeData.getDisconnectReason());
return;
}
switch (result.getResultType()) {
case EXCEPTION:
ctx.channel().attr(kickMessageAttribute)
.set(Constants.INTERNAL_ERROR_MESSAGE);
break;
case DECRYPT_ERROR:
ctx.channel().attr(kickMessageAttribute)
.set(config.getDisconnect().getInvalidKey());
break;
case INVALID_DATA_LENGTH:
ctx.channel().attr(kickMessageAttribute)
.set(config.getDisconnect().getInvalidArgumentsLength());
break;
default:
break;
}
}).handle((v, error) -> {
if (error != null) {
error.printStackTrace();
}
return v;
});
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
super.exceptionCaught(ctx, cause);
if (config.isDebug()) {
cause.printStackTrace();
}
return true;
}
}