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:
@@ -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)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user