diff --git a/core/src/main/java/org/geysermc/floodgate/core/addon/data/HandshakeDataImpl.java b/core/src/main/java/org/geysermc/floodgate/core/addon/data/HandshakeDataImpl.java index 6a9915e1..ee3a7295 100644 --- a/core/src/main/java/org/geysermc/floodgate/core/addon/data/HandshakeDataImpl.java +++ b/core/src/main/java/org/geysermc/floodgate/core/addon/data/HandshakeDataImpl.java @@ -26,6 +26,8 @@ package org.geysermc.floodgate.core.addon.data; import io.netty.channel.Channel; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.Objects; import java.util.UUID; import lombok.Getter; @@ -82,7 +84,9 @@ public class HandshakeDataImpl implements HandshakeData { public FloodgateConnection applyChanges(FloodgateConnection connection, String hostname, FloodgateConfig config) { var newLink = !Objects.equals(connection.linkedPlayer(), this.linkedPlayer) ? this.linkedPlayer : null; - var newIp = !connection.ip().equals(this.ip) ? this.ip : null; + + var thisIp = convertIp(this.ip); + var newIp = !connection.ip().equals(thisIp) ? thisIp : null; // only change when there have been any changes if (newLink == null && newIp == null) { @@ -105,4 +109,23 @@ public class HandshakeDataImpl implements HandshakeData { public UUID getCorrectUniqueId() { return linkedPlayer != null ? linkedPlayer.getJavaUniqueId() : javaUniqueId; } + + private static InetAddress convertIp(String ip) { + String[] sections = ip.split("\\."); + // if not ipv4, expect ipv6 + if (sections.length == 1) { + sections = ip.split(":"); + } + + byte[] addressBytes = new byte[sections.length]; + for (int i = 0; i < sections.length; i++) { + addressBytes[i] = (byte) Integer.parseInt(sections[i]); + } + + try { + return InetAddress.getByAddress(addressBytes); + } catch (UnknownHostException exception) { + throw new RuntimeException(exception); + } + } } diff --git a/core/src/main/java/org/geysermc/floodgate/core/connection/FloodgateConnection.java b/core/src/main/java/org/geysermc/floodgate/core/connection/FloodgateConnection.java index 57e4027d..e7b08079 100644 --- a/core/src/main/java/org/geysermc/floodgate/core/connection/FloodgateConnection.java +++ b/core/src/main/java/org/geysermc/floodgate/core/connection/FloodgateConnection.java @@ -25,6 +25,7 @@ package org.geysermc.floodgate.core.connection; +import java.net.InetAddress; import java.util.UUID; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; @@ -55,7 +56,7 @@ public final class FloodgateConnection implements Connection { private final String languageCode; private final UiProfile uiProfile; private final InputMode inputMode; - private final String ip; + private final InetAddress ip; private final LinkedPlayer linkedPlayer; private final int subscribeId; @@ -109,7 +110,7 @@ public final class FloodgateConnection implements Connection { return inputMode; } - public @NonNull String ip() { + public @NonNull InetAddress ip() { return ip; } @@ -152,7 +153,7 @@ public final class FloodgateConnection implements Connection { public BedrockData toBedrockData() { return BedrockData.of( version, username, xuid, deviceOs.ordinal(), languageCode, uiProfile.ordinal(), - inputMode.ordinal(), ip, linkedPlayer, false, subscribeId, verifyCode + inputMode.ordinal(), ip.getHostAddress(), linkedPlayer, false, subscribeId, verifyCode ); } diff --git a/core/src/main/java/org/geysermc/floodgate/core/connection/FloodgateConnectionBuilder.java b/core/src/main/java/org/geysermc/floodgate/core/connection/FloodgateConnectionBuilder.java index 4974bd93..c8448cdb 100644 --- a/core/src/main/java/org/geysermc/floodgate/core/connection/FloodgateConnectionBuilder.java +++ b/core/src/main/java/org/geysermc/floodgate/core/connection/FloodgateConnectionBuilder.java @@ -25,6 +25,7 @@ package org.geysermc.floodgate.core.connection; +import java.net.InetAddress; import java.util.Objects; import java.util.UUID; import org.checkerframework.checker.nullness.qual.Nullable; @@ -45,7 +46,7 @@ public class FloodgateConnectionBuilder { private String languageCode; private UiProfile uiProfile; private InputMode inputMode; - private String ip; + private InetAddress ip; private LinkedPlayer linkedPlayer; public FloodgateConnectionBuilder(FloodgateConfig config) { @@ -87,7 +88,7 @@ public class FloodgateConnectionBuilder { return this; } - public @This FloodgateConnectionBuilder ip(String ip) { + public @This FloodgateConnectionBuilder ip(InetAddress ip) { this.ip = Objects.requireNonNull(ip); return this; } diff --git a/core/src/main/java/org/geysermc/floodgate/core/connection/codec/CodecUtils.java b/core/src/main/java/org/geysermc/floodgate/core/connection/codec/CodecUtils.java index 0ff1f397..fd4327cb 100644 --- a/core/src/main/java/org/geysermc/floodgate/core/connection/codec/CodecUtils.java +++ b/core/src/main/java/org/geysermc/floodgate/core/connection/codec/CodecUtils.java @@ -27,6 +27,8 @@ package org.geysermc.floodgate.core.connection.codec; import java.io.DataOutputStream; import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.UUID; @@ -49,6 +51,14 @@ final class CodecUtils { stream.write(bytes); } + public static String readUnsignedLong(ByteBuffer buffer) { + return Long.toUnsignedString(buffer.getLong()); + } + + public static void writeUnsignedLong(DataOutputStream stream, String value) throws IOException { + stream.writeLong(Long.parseUnsignedLong(value)); + } + public static int readVarInt(ByteBuffer buffer) { int value = 0; int size = 0; @@ -80,4 +90,20 @@ final class CodecUtils { stream.writeLong(value.getMostSignificantBits()); stream.writeLong(value.getLeastSignificantBits()); } + + public static InetAddress readIp(ByteBuffer buffer) { + var address = new byte[buffer.get()]; + buffer.get(address); + try { + return InetAddress.getByAddress(address); + } catch (UnknownHostException exception) { + throw new RuntimeException(exception); + } + } + + public static void writeIp(DataOutputStream stream, InetAddress ip) throws IOException { + var address = ip.getAddress(); + stream.writeByte(address.length); + stream.write(address); + } } diff --git a/core/src/main/java/org/geysermc/floodgate/core/connection/codec/FloodgateConnectionCodec.java b/core/src/main/java/org/geysermc/floodgate/core/connection/codec/FloodgateConnectionCodec.java index cafb93ce..437a84ce 100644 --- a/core/src/main/java/org/geysermc/floodgate/core/connection/codec/FloodgateConnectionCodec.java +++ b/core/src/main/java/org/geysermc/floodgate/core/connection/codec/FloodgateConnectionCodec.java @@ -26,8 +26,12 @@ package org.geysermc.floodgate.core.connection.codec; import static org.geysermc.floodgate.core.connection.codec.CodecUtils.readBool; +import static org.geysermc.floodgate.core.connection.codec.CodecUtils.readIp; import static org.geysermc.floodgate.core.connection.codec.CodecUtils.readString; +import static org.geysermc.floodgate.core.connection.codec.CodecUtils.readUnsignedLong; +import static org.geysermc.floodgate.core.connection.codec.CodecUtils.writeIp; import static org.geysermc.floodgate.core.connection.codec.CodecUtils.writeString; +import static org.geysermc.floodgate.core.connection.codec.CodecUtils.writeUnsignedLong; import jakarta.inject.Inject; import jakarta.inject.Singleton; @@ -60,12 +64,12 @@ public final class FloodgateConnectionCodec { private void encode0(FloodgateConnection connection, DataOutputStream stream) throws IOException { writeString(stream, connection.version()); writeString(stream, connection.bedrockUsername()); - writeString(stream, connection.xuid()); + writeUnsignedLong(stream, connection.xuid()); stream.writeByte(connection.platform().ordinal()); writeString(stream, connection.languageCode()); stream.writeByte(connection.uiProfile().ordinal()); stream.writeByte(connection.inputMode().ordinal()); - writeString(stream, connection.ip()); + writeIp(stream, connection.ip()); stream.writeBoolean(connection.isLinked()); if (connection.linkedPlayer() != null) { @@ -77,12 +81,12 @@ public final class FloodgateConnectionCodec { var builder = new FloodgateConnectionBuilder(config) .version(readString(buffer)) .username(readString(buffer)) - .xuid(readString(buffer)) + .xuid(readUnsignedLong(buffer)) .deviceOs(BedrockPlatform.fromId(buffer.get())) .languageCode(readString(buffer)) .uiProfile(UiProfile.fromId(buffer.get())) .inputMode(InputMode.fromId(buffer.get())) - .ip(readString(buffer)); + .ip(readIp(buffer)); if (readBool(buffer)) { builder.linkedPlayer(LinkedPlayerCodec.decode(buffer)); }