From af484a425b4eccb125c3e3bf9a965712310b5644 Mon Sep 17 00:00:00 2001 From: Phillipp W <44843453+ChickenPat@users.noreply.github.com> Date: Sat, 25 Jul 2020 19:42:43 +0200 Subject: [PATCH] SRV resolving / Small Handshake rework (#968) Handshake now uses the server address directly from the config and no longer the IP from a domain (Some servers use the address that is given during the handshake) --- .../sponge/GeyserSpongeConfiguration.java | 10 ++++++ .../geysermc/connector/GeyserConnector.java | 34 ++++++++++++++++--- .../configuration/GeyserConfiguration.java | 4 +++ .../ping/GeyserLegacyPingPassthrough.java | 10 +++--- 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java index 79e7621c..d56abe09 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java @@ -195,11 +195,21 @@ public class GeyserSpongeConfiguration implements GeyserConfiguration { return node.getNode("address").getString("127.0.0.1"); } + @Override + public void setAddress(String address) { + node.getNode("address").setValue(address); + } + @Override public int getPort() { return node.getNode("port").getInt(25565); } + @Override + public void setPort(int port) { + node.getNode("port").setValue(port); + } + @Override public String getAuthType() { return node.getNode("auth-type").getString("online"); diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index 89eccda5..527e1248 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -32,10 +32,10 @@ import com.nukkitx.protocol.bedrock.BedrockServer; import com.nukkitx.protocol.bedrock.v407.Bedrock_v407; import lombok.Getter; import lombok.Setter; -import org.geysermc.connector.common.AuthType; -import org.geysermc.connector.common.PlatformType; import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.command.CommandManager; +import org.geysermc.connector.common.AuthType; +import org.geysermc.connector.common.PlatformType; import org.geysermc.connector.configuration.GeyserConfiguration; import org.geysermc.connector.metrics.Metrics; import org.geysermc.connector.network.ConnectorServerEventHandler; @@ -51,17 +51,19 @@ import org.geysermc.connector.network.translators.item.PotionMixRegistry; import org.geysermc.connector.network.translators.sound.SoundHandlerRegistry; import org.geysermc.connector.network.translators.sound.SoundRegistry; import org.geysermc.connector.network.translators.world.WorldManager; -import org.geysermc.connector.utils.LanguageUtils; import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator; import org.geysermc.connector.utils.DimensionUtils; import org.geysermc.connector.utils.DockerCheck; +import org.geysermc.connector.utils.LanguageUtils; import org.geysermc.connector.utils.LocaleUtils; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.InitialDirContext; import java.net.InetSocketAddress; import java.text.DecimalFormat; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; @@ -78,6 +80,8 @@ public class GeyserConnector { public static final String NAME = "Geyser"; public static final String VERSION = "DEV"; // A fallback for running in IDEs + private static final String IP_REGEX = "\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b"; + private final List players = new ArrayList<>(); private static GeyserConnector instance; @@ -136,8 +140,28 @@ public class GeyserConnector { if (platformType != PlatformType.STANDALONE) { DockerCheck.check(bootstrap); } + String remoteAddress = config.getRemote().getAddress(); + int remotePort = config.getRemote().getPort(); + // Filters whether it is not an IP address or localhost, because otherwise it is not possible to find out an SRV entry. + if ((config.isLegacyPingPassthrough() || platformType == PlatformType.STANDALONE) && !remoteAddress.matches(IP_REGEX) && !remoteAddress.equalsIgnoreCase("localhost")) { + try { + // Searches for a server address and a port from a SRV record of the specified host name + InitialDirContext ctx = new InitialDirContext(); + Attribute attr = ctx.getAttributes("dns:///_minecraft._tcp." + remoteAddress, new String[]{"SRV"}).get("SRV"); + // size > 0 = SRV entry found + if (attr.size() > 0) { + String[] record = ((String) attr.get(0)).split(" "); + // Overwrites the existing address and port with that from the SRV record. + config.getRemote().setAddress(remoteAddress = record[3]); + config.getRemote().setPort(remotePort = Integer.parseInt(record[2])); + logger.debug("Found SRV record \"" + remoteAddress + ":" + remotePort + "\""); + } + } catch (NamingException ex) { + ex.printStackTrace(); + } + } - remoteServer = new RemoteServer(config.getRemote().getAddress(), config.getRemote().getPort()); + remoteServer = new RemoteServer(config.getRemote().getAddress(), remotePort); authType = AuthType.getByName(config.getRemote().getAuthType()); if (config.isAboveBedrockNetherBuilding()) diff --git a/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java b/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java index 5727a902..a8bc0a9d 100644 --- a/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java +++ b/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java @@ -92,6 +92,10 @@ public interface GeyserConfiguration { String getAddress(); int getPort(); + + void setAddress(String address); + + void setPort(int port); String getAuthType(); } diff --git a/connector/src/main/java/org/geysermc/connector/ping/GeyserLegacyPingPassthrough.java b/connector/src/main/java/org/geysermc/connector/ping/GeyserLegacyPingPassthrough.java index aa9e0503..ec4e0d7f 100644 --- a/connector/src/main/java/org/geysermc/connector/ping/GeyserLegacyPingPassthrough.java +++ b/connector/src/main/java/org/geysermc/connector/ping/GeyserLegacyPingPassthrough.java @@ -79,15 +79,17 @@ public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runn public void run() { try { Socket socket = new Socket(); - socket.connect(new InetSocketAddress(connector.getConfig().getRemote().getAddress(), connector.getConfig().getRemote().getPort()), 5000); + String address = connector.getConfig().getRemote().getAddress(); + int port = connector.getConfig().getRemote().getPort(); + socket.connect(new InetSocketAddress(address, port), 5000); ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream(); DataOutputStream handshake = new DataOutputStream(byteArrayStream); handshake.write(0x0); VarInts.writeUnsignedInt(handshake, MinecraftConstants.PROTOCOL_VERSION); - VarInts.writeUnsignedInt(handshake, socket.getInetAddress().getHostAddress().length()); - handshake.writeBytes(socket.getInetAddress().getHostAddress()); - handshake.writeShort(socket.getPort()); + VarInts.writeUnsignedInt(handshake, address.length()); + handshake.writeBytes(address); + handshake.writeShort(port); VarInts.writeUnsignedInt(handshake, 1); DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());