forked from MinecraftUtilities/Backend
add dns records to the server response
This commit is contained in:
parent
d156d2cb3b
commit
0ea69f86f9
@ -34,6 +34,6 @@ public class Main {
|
|||||||
}
|
}
|
||||||
log.info("Found configuration at '{}'", config.getAbsolutePath()); // Log the found config
|
log.info("Found configuration at '{}'", config.getAbsolutePath()); // Log the found config
|
||||||
|
|
||||||
SpringApplication.run(Main.class, args);
|
SpringApplication.run(Main.class, args); // Start the application
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,13 +1,13 @@
|
|||||||
package cc.fascinated.common;
|
package cc.fascinated.common;
|
||||||
|
|
||||||
|
import cc.fascinated.model.dns.impl.ARecord;
|
||||||
|
import cc.fascinated.model.dns.impl.SRVRecord;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
|
import org.xbill.DNS.Lookup;
|
||||||
import org.xbill.DNS.Record;
|
import org.xbill.DNS.Record;
|
||||||
import org.xbill.DNS.*;
|
import org.xbill.DNS.Type;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Braydon
|
* @author Braydon
|
||||||
@ -17,43 +17,42 @@ public final class DNSUtils {
|
|||||||
private static final String SRV_QUERY_PREFIX = "_minecraft._tcp.%s";
|
private static final String SRV_QUERY_PREFIX = "_minecraft._tcp.%s";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve the hostname to an {@link InetSocketAddress}.
|
* Get the resolved address and port of the
|
||||||
|
* given hostname by resolving the SRV records.
|
||||||
*
|
*
|
||||||
* @param hostname the hostname to resolve
|
* @param hostname the hostname to resolve
|
||||||
* @return the resolved {@link InetSocketAddress}
|
* @return the resolved address and port, null if none
|
||||||
*/
|
*/
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static InetSocketAddress resolveSRV(@NonNull String hostname) {
|
public static SRVRecord resolveSRV(@NonNull String hostname) {
|
||||||
Record[] records = new Lookup(SRV_QUERY_PREFIX.formatted(hostname), Type.SRV).run(); // Resolve SRV records
|
Record[] records = new Lookup(SRV_QUERY_PREFIX.formatted(hostname), Type.SRV).run(); // Resolve SRV records
|
||||||
if (records == null) { // No records exist
|
if (records == null) { // No records exist
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String host = null;
|
SRVRecord result = null;
|
||||||
int port = -1;
|
|
||||||
for (Record record : records) {
|
for (Record record : records) {
|
||||||
SRVRecord srv = (SRVRecord) record;
|
result = new SRVRecord((org.xbill.DNS.SRVRecord) record);
|
||||||
host = srv.getTarget().toString().replaceFirst("\\.$", "");
|
|
||||||
port = srv.getPort();
|
|
||||||
}
|
}
|
||||||
return host == null ? null : new InetSocketAddress(host, port);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve the hostname to an {@link InetAddress}.
|
* Get the resolved address of the given
|
||||||
|
* hostname by resolving the A records.
|
||||||
*
|
*
|
||||||
* @param hostname the hostname to resolve
|
* @param hostname the hostname to resolve
|
||||||
* @return the resolved {@link InetAddress}
|
* @return the resolved address, null if none
|
||||||
*/
|
*/
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static InetAddress resolveA(@NonNull String hostname) {
|
public static ARecord resolveA(@NonNull String hostname) {
|
||||||
Record[] records = new Lookup(hostname, Type.A).run(); // Resolve A records
|
Record[] records = new Lookup(hostname, Type.A).run(); // Resolve A records
|
||||||
if (records == null) { // No records exist
|
if (records == null) { // No records exist
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
InetAddress address = null;
|
ARecord result = null;
|
||||||
for (Record record : records) {
|
for (Record record : records) {
|
||||||
address = ((ARecord) record).getAddress();
|
result = new ARecord((org.xbill.DNS.ARecord) record);
|
||||||
}
|
}
|
||||||
return address;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,14 +12,14 @@ public class HomeController {
|
|||||||
/**
|
/**
|
||||||
* The example UUID.
|
* The example UUID.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("FieldCanBeLocal")
|
|
||||||
private final String exampleUuid = "eeab5f8a-18dd-4d58-af78-2b3c4543da48";
|
private final String exampleUuid = "eeab5f8a-18dd-4d58-af78-2b3c4543da48";
|
||||||
|
private final String exampleServer = "eeab5f8a-18dd-4d58-af78-2b3c4543da48";
|
||||||
|
|
||||||
@RequestMapping(value = "/")
|
@RequestMapping(value = "/")
|
||||||
public String home(Model model) {
|
public String home(Model model) {
|
||||||
model.addAttribute("player_example_url", Config.INSTANCE.getWebPublicUrl() + "/player/" + exampleUuid);
|
model.addAttribute("player_example_url", Config.INSTANCE.getWebPublicUrl() + "/player/" + exampleUuid);
|
||||||
model.addAttribute("java_server_example_url", Config.INSTANCE.getWebPublicUrl() + "/server/java/play.hypixel.net");
|
model.addAttribute("java_server_example_url", Config.INSTANCE.getWebPublicUrl() + "/server/java/" + exampleServer);
|
||||||
model.addAttribute("swagger_url", Config.INSTANCE.getWebPublicUrl() + "/swagger-ui.html");
|
model.addAttribute("swagger_url", Config.INSTANCE.getWebPublicUrl() + "/docs");
|
||||||
return "index";
|
return "index";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
29
src/main/java/cc.fascinated/model/dns/DNSRecord.java
Normal file
29
src/main/java/cc.fascinated/model/dns/DNSRecord.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package cc.fascinated.model.dns;
|
||||||
|
|
||||||
|
import io.micrometer.common.lang.NonNull;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Setter @Getter
|
||||||
|
@NoArgsConstructor @AllArgsConstructor
|
||||||
|
public abstract class DNSRecord {
|
||||||
|
/**
|
||||||
|
* The type of this record.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
private Type type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The TTL (Time To Live) of this record.
|
||||||
|
*/
|
||||||
|
private long ttl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types of a record.
|
||||||
|
*/
|
||||||
|
public enum Type {
|
||||||
|
A, SRV
|
||||||
|
}
|
||||||
|
}
|
24
src/main/java/cc.fascinated/model/dns/impl/ARecord.java
Normal file
24
src/main/java/cc.fascinated/model/dns/impl/ARecord.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package cc.fascinated.model.dns.impl;
|
||||||
|
|
||||||
|
import cc.fascinated.model.dns.DNSRecord;
|
||||||
|
import io.micrometer.common.lang.NonNull;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
|
||||||
|
@Setter @Getter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public final class ARecord extends DNSRecord {
|
||||||
|
/**
|
||||||
|
* The address of this record, null if unresolved.
|
||||||
|
*/
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
public ARecord(@NonNull org.xbill.DNS.ARecord bootstrap) {
|
||||||
|
super(Type.A, bootstrap.getTTL());
|
||||||
|
InetAddress address = bootstrap.getAddress();
|
||||||
|
this.address = address == null ? null : address.getHostAddress();
|
||||||
|
}
|
||||||
|
}
|
53
src/main/java/cc.fascinated/model/dns/impl/SRVRecord.java
Normal file
53
src/main/java/cc.fascinated/model/dns/impl/SRVRecord.java
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package cc.fascinated.model.dns.impl;
|
||||||
|
|
||||||
|
import cc.fascinated.model.dns.DNSRecord;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import io.micrometer.common.lang.NonNull;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
|
@Setter @Getter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public final class SRVRecord extends DNSRecord {
|
||||||
|
/**
|
||||||
|
* The priority of this record.
|
||||||
|
*/
|
||||||
|
private int priority;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The weight of this record.
|
||||||
|
*/
|
||||||
|
private int weight;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The port of this record.
|
||||||
|
*/
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The target of this record.
|
||||||
|
*/
|
||||||
|
@NonNull private String target;
|
||||||
|
|
||||||
|
public SRVRecord(@NonNull org.xbill.DNS.SRVRecord bootstrap) {
|
||||||
|
super(Type.SRV, bootstrap.getTTL());
|
||||||
|
priority = bootstrap.getPriority();
|
||||||
|
weight = bootstrap.getWeight();
|
||||||
|
port = bootstrap.getPort();
|
||||||
|
target = bootstrap.getTarget().toString().replaceFirst("\\.$", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a socket address from
|
||||||
|
* the target and port.
|
||||||
|
*
|
||||||
|
* @return the socket address
|
||||||
|
*/
|
||||||
|
@NonNull @JsonIgnore
|
||||||
|
public InetSocketAddress getSocketAddress() {
|
||||||
|
return new InetSocketAddress(target, port);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package cc.fascinated.model.server;
|
package cc.fascinated.model.server;
|
||||||
|
|
||||||
|
import cc.fascinated.model.dns.DNSRecord;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,7 +13,7 @@ public final class BedrockMinecraftServer extends MinecraftServer {
|
|||||||
/**
|
/**
|
||||||
* The unique ID of this server.
|
* The unique ID of this server.
|
||||||
*/
|
*/
|
||||||
@EqualsAndHashCode.Include @NonNull private final String uniqueId;
|
@EqualsAndHashCode.Include @NonNull private final String id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The edition of this server.
|
* The edition of this server.
|
||||||
@ -29,11 +30,11 @@ public final class BedrockMinecraftServer extends MinecraftServer {
|
|||||||
*/
|
*/
|
||||||
@NonNull private final GameMode gamemode;
|
@NonNull private final GameMode gamemode;
|
||||||
|
|
||||||
private BedrockMinecraftServer(@NonNull String uniqueId, @NonNull String hostname, String ip, int port,
|
private BedrockMinecraftServer(@NonNull String id, @NonNull String hostname, String ip, int port, @NonNull DNSRecord[] records,
|
||||||
@NonNull Edition edition, @NonNull Version version, @NonNull Players players,
|
@NonNull Edition edition, @NonNull Version version, @NonNull Players players, @NonNull MOTD motd,
|
||||||
@NonNull MOTD motd, @NonNull GameMode gamemode) {
|
@NonNull GameMode gamemode) {
|
||||||
super(hostname, ip, port, motd, players);
|
super(hostname, ip, port, records, motd, players);
|
||||||
this.uniqueId = uniqueId;
|
this.id = id;
|
||||||
this.edition = edition;
|
this.edition = edition;
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.gamemode = gamemode;
|
this.gamemode = gamemode;
|
||||||
@ -49,14 +50,25 @@ public final class BedrockMinecraftServer extends MinecraftServer {
|
|||||||
* @return the Bedrock Minecraft server
|
* @return the Bedrock Minecraft server
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static BedrockMinecraftServer create(@NonNull String hostname, String ip, int port, @NonNull String token) {
|
public static BedrockMinecraftServer create(@NonNull String hostname, String ip, int port, DNSRecord[] records, @NonNull String token) {
|
||||||
String[] split = token.split(";"); // Split the token
|
String[] split = token.split(";"); // Split the token
|
||||||
Edition edition = Edition.valueOf(split[0]);
|
Edition edition = Edition.valueOf(split[0]);
|
||||||
Version version = new Version(Integer.parseInt(split[2]), split[3]);
|
Version version = new Version(Integer.parseInt(split[2]), split[3]);
|
||||||
Players players = new Players(Integer.parseInt(split[4]), Integer.parseInt(split[5]), null);
|
Players players = new Players(Integer.parseInt(split[4]), Integer.parseInt(split[5]), null);
|
||||||
MOTD motd = MOTD.create(split[1] + "\n" + split[7]);
|
MOTD motd = MOTD.create(split[1] + "\n" + split[7]);
|
||||||
GameMode gameMode = new GameMode(split[8], Integer.parseInt(split[9]));
|
GameMode gameMode = new GameMode(split[8], Integer.parseInt(split[9]));
|
||||||
return new BedrockMinecraftServer(split[6], hostname, ip, port, edition, version, players, motd, gameMode);
|
return new BedrockMinecraftServer(
|
||||||
|
split[6],
|
||||||
|
hostname,
|
||||||
|
ip,
|
||||||
|
port,
|
||||||
|
records,
|
||||||
|
edition,
|
||||||
|
version,
|
||||||
|
players,
|
||||||
|
motd,
|
||||||
|
gameMode
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,6 +4,7 @@ import cc.fascinated.Main;
|
|||||||
import cc.fascinated.common.JavaMinecraftVersion;
|
import cc.fascinated.common.JavaMinecraftVersion;
|
||||||
import cc.fascinated.common.ServerUtils;
|
import cc.fascinated.common.ServerUtils;
|
||||||
import cc.fascinated.config.Config;
|
import cc.fascinated.config.Config;
|
||||||
|
import cc.fascinated.model.dns.DNSRecord;
|
||||||
import cc.fascinated.model.token.JavaServerStatusToken;
|
import cc.fascinated.model.token.JavaServerStatusToken;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
@ -60,14 +61,14 @@ public final class JavaMinecraftServer extends MinecraftServer {
|
|||||||
private boolean previewsChat;
|
private boolean previewsChat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The mojang banned status of the server.
|
* The mojang blocked status for the server.
|
||||||
*/
|
*/
|
||||||
private boolean mojangBanned;
|
private boolean mojangBlocked;
|
||||||
|
|
||||||
public JavaMinecraftServer(String hostname, String ip, int port, MOTD motd, Players players, @NonNull Version version,
|
public JavaMinecraftServer(String hostname, String ip, int port, MOTD motd, Players players, DNSRecord[] records,
|
||||||
Favicon favicon, ForgeModInfo modInfo, ForgeData forgeData, boolean preventsChatReports,
|
@NonNull Version version, Favicon favicon, ForgeModInfo modInfo, ForgeData forgeData,
|
||||||
boolean enforcesSecureChat, boolean previewsChat) {
|
boolean preventsChatReports, boolean enforcesSecureChat, boolean previewsChat) {
|
||||||
super(hostname, ip, port, motd, players);
|
super(hostname, ip, port, records, motd, players);
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.favicon = favicon;
|
this.favicon = favicon;
|
||||||
this.modInfo = modInfo;
|
this.modInfo = modInfo;
|
||||||
@ -87,7 +88,7 @@ public final class JavaMinecraftServer extends MinecraftServer {
|
|||||||
* @return the Java Minecraft server
|
* @return the Java Minecraft server
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static JavaMinecraftServer create(@NonNull String hostname, String ip, int port, @NonNull JavaServerStatusToken token) {
|
public static JavaMinecraftServer create(@NonNull String hostname, String ip, int port, DNSRecord[] records, @NonNull JavaServerStatusToken token) {
|
||||||
String motdString = token.getDescription() instanceof String ? (String) token.getDescription() : null;
|
String motdString = token.getDescription() instanceof String ? (String) token.getDescription() : null;
|
||||||
if (motdString == null) { // Not a string motd, convert from Json
|
if (motdString == null) { // Not a string motd, convert from Json
|
||||||
motdString = new TextComponent(ComponentSerializer.parse(Main.GSON.toJson(token.getDescription()))).toLegacyText();
|
motdString = new TextComponent(ComponentSerializer.parse(Main.GSON.toJson(token.getDescription()))).toLegacyText();
|
||||||
@ -98,6 +99,7 @@ public final class JavaMinecraftServer extends MinecraftServer {
|
|||||||
port,
|
port,
|
||||||
MinecraftServer.MOTD.create(motdString),
|
MinecraftServer.MOTD.create(motdString),
|
||||||
token.getPlayers(),
|
token.getPlayers(),
|
||||||
|
records,
|
||||||
token.getVersion().detailedCopy(),
|
token.getVersion().detailedCopy(),
|
||||||
JavaMinecraftServer.Favicon.create(token.getFavicon(), ServerUtils.getAddress(hostname, port)),
|
JavaMinecraftServer.Favicon.create(token.getFavicon(), ServerUtils.getAddress(hostname, port)),
|
||||||
token.getModInfo(),
|
token.getModInfo(),
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
package cc.fascinated.model.server;
|
package cc.fascinated.model.server;
|
||||||
|
|
||||||
import cc.fascinated.common.ColorUtils;
|
import cc.fascinated.common.ColorUtils;
|
||||||
|
import cc.fascinated.model.dns.DNSRecord;
|
||||||
import cc.fascinated.service.pinger.MinecraftServerPinger;
|
import cc.fascinated.service.pinger.MinecraftServerPinger;
|
||||||
import cc.fascinated.service.pinger.impl.BedrockMinecraftServerPinger;
|
import cc.fascinated.service.pinger.impl.BedrockMinecraftServerPinger;
|
||||||
import cc.fascinated.service.pinger.impl.JavaMinecraftServerPinger;
|
import cc.fascinated.service.pinger.impl.JavaMinecraftServerPinger;
|
||||||
import io.micrometer.common.lang.NonNull;
|
import io.micrometer.common.lang.NonNull;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -15,8 +17,10 @@ import java.util.UUID;
|
|||||||
/**
|
/**
|
||||||
* @author Braydon
|
* @author Braydon
|
||||||
*/
|
*/
|
||||||
@AllArgsConstructor @Getter @ToString
|
@AllArgsConstructor
|
||||||
|
@Getter @Setter
|
||||||
public class MinecraftServer {
|
public class MinecraftServer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The hostname of the server.
|
* The hostname of the server.
|
||||||
*/
|
*/
|
||||||
@ -32,6 +36,11 @@ public class MinecraftServer {
|
|||||||
*/
|
*/
|
||||||
private final int port;
|
private final int port;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The DNS records for the server.
|
||||||
|
*/
|
||||||
|
private final DNSRecord[] records;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The motd for the server.
|
* The motd for the server.
|
||||||
*/
|
*/
|
||||||
@ -40,7 +49,7 @@ public class MinecraftServer {
|
|||||||
/**
|
/**
|
||||||
* The players on the server.
|
* The players on the server.
|
||||||
*/
|
*/
|
||||||
private Players players;
|
private final Players players;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A platform a Minecraft
|
* A platform a Minecraft
|
||||||
|
@ -5,6 +5,9 @@ import cc.fascinated.common.EnumUtils;
|
|||||||
import cc.fascinated.exception.impl.BadRequestException;
|
import cc.fascinated.exception.impl.BadRequestException;
|
||||||
import cc.fascinated.exception.impl.ResourceNotFoundException;
|
import cc.fascinated.exception.impl.ResourceNotFoundException;
|
||||||
import cc.fascinated.model.cache.CachedMinecraftServer;
|
import cc.fascinated.model.cache.CachedMinecraftServer;
|
||||||
|
import cc.fascinated.model.dns.DNSRecord;
|
||||||
|
import cc.fascinated.model.dns.impl.ARecord;
|
||||||
|
import cc.fascinated.model.dns.impl.SRVRecord;
|
||||||
import cc.fascinated.model.server.JavaMinecraftServer;
|
import cc.fascinated.model.server.JavaMinecraftServer;
|
||||||
import cc.fascinated.model.server.MinecraftServer;
|
import cc.fascinated.model.server.MinecraftServer;
|
||||||
import cc.fascinated.repository.MinecraftServerCacheRepository;
|
import cc.fascinated.repository.MinecraftServerCacheRepository;
|
||||||
@ -13,7 +16,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@Service @Log4j2
|
@Service @Log4j2
|
||||||
@ -63,21 +68,32 @@ public class ServerService {
|
|||||||
return cached.get();
|
return cached.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the SRV record if the platform is Java
|
List<DNSRecord> records = new ArrayList<>(); // The resolved DNS records for the server
|
||||||
InetSocketAddress address = platform == MinecraftServer.Platform.JAVA ? DNSUtils.resolveSRV(hostname) : null;
|
|
||||||
if (address != null) {
|
SRVRecord srvRecord = platform == MinecraftServer.Platform.JAVA ? DNSUtils.resolveSRV(hostname) : null; // Resolve the SRV record
|
||||||
hostname = address.getHostName();
|
if (srvRecord != null) { // SRV was resolved, use the hostname and port
|
||||||
|
records.add(srvRecord); // Going to need this for later
|
||||||
|
InetSocketAddress socketAddress = srvRecord.getSocketAddress();
|
||||||
|
hostname = socketAddress.getHostName();
|
||||||
|
port = socketAddress.getPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
ARecord aRecord = DNSUtils.resolveA(hostname); // Resolve the A record so we can get the IPv4 address
|
||||||
|
String ip = aRecord == null ? null : aRecord.getAddress(); // Get the IP address
|
||||||
|
if (ip != null) { // Was the IP resolved?
|
||||||
|
records.add(aRecord); // Going to need this for later
|
||||||
|
log.info("Resolved hostname: {} -> {}", hostname, ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedMinecraftServer server = new CachedMinecraftServer(
|
CachedMinecraftServer server = new CachedMinecraftServer(
|
||||||
key,
|
key,
|
||||||
platform.getPinger().ping(hostname, port),
|
platform.getPinger().ping(hostname, ip, port, records.toArray(new DNSRecord[0])),
|
||||||
System.currentTimeMillis()
|
System.currentTimeMillis()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check if the server is blocked by Mojang
|
// Check if the server is blocked by Mojang
|
||||||
if (platform == MinecraftServer.Platform.JAVA) {
|
if (platform == MinecraftServer.Platform.JAVA) {
|
||||||
((JavaMinecraftServer) server.getServer()).setMojangBanned(mojangService.isServerBlocked(hostname));
|
((JavaMinecraftServer) server.getServer()).setMojangBlocked(mojangService.isServerBlocked(hostname));
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("Found server: {}:{}", hostname, port);
|
log.info("Found server: {}:{}", hostname, port);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package cc.fascinated.service.pinger;
|
package cc.fascinated.service.pinger;
|
||||||
|
|
||||||
|
import cc.fascinated.model.dns.DNSRecord;
|
||||||
import cc.fascinated.model.server.MinecraftServer;
|
import cc.fascinated.model.server.MinecraftServer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -7,5 +8,5 @@ import cc.fascinated.model.server.MinecraftServer;
|
|||||||
* @param <T> the type of server to ping
|
* @param <T> the type of server to ping
|
||||||
*/
|
*/
|
||||||
public interface MinecraftServerPinger<T extends MinecraftServer> {
|
public interface MinecraftServerPinger<T extends MinecraftServer> {
|
||||||
T ping(String hostname, int port);
|
T ping(String hostname, String ip, int port, DNSRecord[] records);
|
||||||
}
|
}
|
@ -1,17 +1,19 @@
|
|||||||
package cc.fascinated.service.pinger.impl;
|
package cc.fascinated.service.pinger.impl;
|
||||||
|
|
||||||
import cc.fascinated.common.DNSUtils;
|
|
||||||
import cc.fascinated.common.packet.impl.bedrock.BedrockPacketUnconnectedPing;
|
import cc.fascinated.common.packet.impl.bedrock.BedrockPacketUnconnectedPing;
|
||||||
import cc.fascinated.common.packet.impl.bedrock.BedrockPacketUnconnectedPong;
|
import cc.fascinated.common.packet.impl.bedrock.BedrockPacketUnconnectedPong;
|
||||||
import cc.fascinated.exception.impl.BadRequestException;
|
import cc.fascinated.exception.impl.BadRequestException;
|
||||||
import cc.fascinated.exception.impl.ResourceNotFoundException;
|
import cc.fascinated.exception.impl.ResourceNotFoundException;
|
||||||
|
import cc.fascinated.model.dns.DNSRecord;
|
||||||
import cc.fascinated.model.server.BedrockMinecraftServer;
|
import cc.fascinated.model.server.BedrockMinecraftServer;
|
||||||
import cc.fascinated.service.pinger.MinecraftServerPinger;
|
import cc.fascinated.service.pinger.MinecraftServerPinger;
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.*;
|
import java.net.DatagramSocket;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketTimeoutException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link MinecraftServerPinger} for pinging
|
* The {@link MinecraftServerPinger} for pinging
|
||||||
@ -31,12 +33,7 @@ public final class BedrockMinecraftServerPinger implements MinecraftServerPinger
|
|||||||
* @return the server that was pinged
|
* @return the server that was pinged
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public BedrockMinecraftServer ping(@NonNull String hostname, int port) {
|
public BedrockMinecraftServer ping(String hostname, String ip, int port, DNSRecord[] records) {
|
||||||
InetAddress inetAddress = DNSUtils.resolveA(hostname); // Resolve the hostname to an IP address
|
|
||||||
String ip = inetAddress == null ? null : inetAddress.getHostAddress(); // Get the IP address
|
|
||||||
if (ip != null) { // Was the IP resolved?
|
|
||||||
log.info("Resolved hostname: {} -> {}", hostname, ip);
|
|
||||||
}
|
|
||||||
log.info("Pinging {}:{}...", hostname, port);
|
log.info("Pinging {}:{}...", hostname, port);
|
||||||
long before = System.currentTimeMillis(); // Timestamp before pinging
|
long before = System.currentTimeMillis(); // Timestamp before pinging
|
||||||
|
|
||||||
@ -58,7 +55,7 @@ public final class BedrockMinecraftServerPinger implements MinecraftServerPinger
|
|||||||
if (response == null) { // No pong response
|
if (response == null) { // No pong response
|
||||||
throw new ResourceNotFoundException("Server didn't respond to ping");
|
throw new ResourceNotFoundException("Server didn't respond to ping");
|
||||||
}
|
}
|
||||||
return BedrockMinecraftServer.create(hostname, ip, port, response); // Return the server
|
return BedrockMinecraftServer.create(hostname, ip, port, records, response); // Return the server
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
if (ex instanceof UnknownHostException) {
|
if (ex instanceof UnknownHostException) {
|
||||||
throw new BadRequestException("Unknown hostname: %s".formatted(hostname));
|
throw new BadRequestException("Unknown hostname: %s".formatted(hostname));
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package cc.fascinated.service.pinger.impl;
|
package cc.fascinated.service.pinger.impl;
|
||||||
|
|
||||||
import cc.fascinated.Main;
|
import cc.fascinated.Main;
|
||||||
import cc.fascinated.common.DNSUtils;
|
|
||||||
import cc.fascinated.common.JavaMinecraftVersion;
|
import cc.fascinated.common.JavaMinecraftVersion;
|
||||||
import cc.fascinated.common.ServerUtils;
|
import cc.fascinated.common.ServerUtils;
|
||||||
import cc.fascinated.common.packet.impl.java.JavaPacketHandshakingInSetProtocol;
|
import cc.fascinated.common.packet.impl.java.JavaPacketHandshakingInSetProtocol;
|
||||||
import cc.fascinated.common.packet.impl.java.JavaPacketStatusInStart;
|
import cc.fascinated.common.packet.impl.java.JavaPacketStatusInStart;
|
||||||
import cc.fascinated.exception.impl.BadRequestException;
|
import cc.fascinated.exception.impl.BadRequestException;
|
||||||
import cc.fascinated.exception.impl.ResourceNotFoundException;
|
import cc.fascinated.exception.impl.ResourceNotFoundException;
|
||||||
|
import cc.fascinated.model.dns.DNSRecord;
|
||||||
import cc.fascinated.model.server.JavaMinecraftServer;
|
import cc.fascinated.model.server.JavaMinecraftServer;
|
||||||
import cc.fascinated.model.token.JavaServerStatusToken;
|
import cc.fascinated.model.token.JavaServerStatusToken;
|
||||||
import cc.fascinated.service.pinger.MinecraftServerPinger;
|
import cc.fascinated.service.pinger.MinecraftServerPinger;
|
||||||
@ -26,12 +26,7 @@ public final class JavaMinecraftServerPinger implements MinecraftServerPinger<Ja
|
|||||||
private static final int TIMEOUT = 1500; // The timeout for the socket
|
private static final int TIMEOUT = 1500; // The timeout for the socket
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JavaMinecraftServer ping(String hostname, int port) {
|
public JavaMinecraftServer ping(String hostname, String ip, int port, DNSRecord[] records) {
|
||||||
InetAddress inetAddress = DNSUtils.resolveA(hostname); // Resolve the hostname to an IP address
|
|
||||||
String ip = inetAddress == null ? null : inetAddress.getHostAddress(); // Get the IP address
|
|
||||||
if (ip != null) { // Was the IP resolved?
|
|
||||||
log.info("Resolved hostname: {} -> {}", hostname, ip);
|
|
||||||
}
|
|
||||||
log.info("Pinging {}:{}...", hostname, port);
|
log.info("Pinging {}:{}...", hostname, port);
|
||||||
|
|
||||||
// Open a socket connection to the server
|
// Open a socket connection to the server
|
||||||
@ -49,7 +44,7 @@ public final class JavaMinecraftServerPinger implements MinecraftServerPinger<Ja
|
|||||||
JavaPacketStatusInStart packetStatusInStart = new JavaPacketStatusInStart();
|
JavaPacketStatusInStart packetStatusInStart = new JavaPacketStatusInStart();
|
||||||
packetStatusInStart.process(inputStream, outputStream);
|
packetStatusInStart.process(inputStream, outputStream);
|
||||||
JavaServerStatusToken token = Main.GSON.fromJson(packetStatusInStart.getResponse(), JavaServerStatusToken.class);
|
JavaServerStatusToken token = Main.GSON.fromJson(packetStatusInStart.getResponse(), JavaServerStatusToken.class);
|
||||||
return JavaMinecraftServer.create(hostname, ip, port, token);
|
return JavaMinecraftServer.create(hostname, ip, port, records, token);
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
if (ex instanceof UnknownHostException) {
|
if (ex instanceof UnknownHostException) {
|
||||||
|
Loading…
Reference in New Issue
Block a user